Skip to content

Commit 953a403

Browse files
authored
Pre-decompress query updates (#302)
This dramatically improves performance by avoiding the default implementation of BrotliStream.ReadByte() inherited from Stream, which allocates an array per byte read. ## API - [ ] This is an API breaking change to the SDK *If the API is breaking, please state below what will break* ## Requires SpacetimeDB PRs ## Testsuite SpacetimeDB branch name: master ## Testing *Write instructions for a test that you performed for this PR* - [ ] Describe a test for this PR that you have completed
1 parent 8c1b4a9 commit 953a403

File tree

2 files changed

+16
-4
lines changed

2 files changed

+16
-4
lines changed

src/MultiDictionary.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ public bool Add(TKey key, TValue value)
7474
Debug.Assert(key != null);
7575
if (RawDict.TryGetValue(key, out var result))
7676
{
77-
Debug.Assert(ValueComparer.Equals(value, result.Value), $"Added key-value pair with mismatched value to existing data, {key} {value} {result.Value}");
77+
Debug.Assert(ValueComparer.Equals(value, result.Value));
7878
RawDict[key] = (value, result.Multiplicity + 1);
7979
return false;
8080
}
@@ -252,7 +252,7 @@ public void Apply(MultiDictionaryDelta<TKey, TValue> delta, List<KeyValuePair<TK
252252
// However, it may remove the key-value pair entirely.
253253

254254
var theirDelta = their.NonValueChange;
255-
Debug.Assert(ValueComparer.Equals(my.Value, theirDelta.Value), $"mismatched value change: {my.Value} {theirDelta.Value} {their}");
255+
Debug.Assert(ValueComparer.Equals(my.Value, theirDelta.Value));
256256
var newMultiplicity = (int)my.Multiplicity + theirDelta.Delta;
257257
if (newMultiplicity > 0)
258258
{

src/SpacetimeDBClient.cs

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -314,7 +314,13 @@ private static ServerMessage DecompressDecodeMessage(byte[] bytes)
314314
_ => throw new InvalidOperationException("Unknown compression type"),
315315
};
316316

317-
return new ServerMessage.BSATN().Read(new BinaryReader(decompressedStream));
317+
// TODO: consider pooling these.
318+
// DO NOT TRY TO TAKE THIS OUT. The BrotliStream ReadByte() implementation allocates an array
319+
// PER BYTE READ. You have to do it all at once to avoid that problem.
320+
MemoryStream memoryStream = new MemoryStream();
321+
decompressedStream.CopyTo(memoryStream);
322+
memoryStream.Seek(0, SeekOrigin.Begin);
323+
return new ServerMessage.BSATN().Read(new BinaryReader(memoryStream));
318324
}
319325

320326
private static QueryUpdate DecompressDecodeQueryUpdate(CompressableQueryUpdate update)
@@ -338,7 +344,13 @@ private static QueryUpdate DecompressDecodeQueryUpdate(CompressableQueryUpdate u
338344
throw new InvalidOperationException();
339345
}
340346

341-
return new QueryUpdate.BSATN().Read(new BinaryReader(decompressedStream));
347+
// TODO: consider pooling these.
348+
// DO NOT TRY TO TAKE THIS OUT. The BrotliStream ReadByte() implementation allocates an array
349+
// PER BYTE READ. You have to do it all at once to avoid that problem.
350+
MemoryStream memoryStream = new MemoryStream();
351+
decompressedStream.CopyTo(memoryStream);
352+
memoryStream.Seek(0, SeekOrigin.Begin);
353+
return new QueryUpdate.BSATN().Read(new BinaryReader(memoryStream));
342354
}
343355

344356
private static IEnumerable<byte[]> BsatnRowListIter(BsatnRowList list)

0 commit comments

Comments
 (0)