Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New Span-based serialization logic (followup for #7351) #7576

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
c855561
initial implementation of buffer encoding
jtattermusch May 28, 2020
a329764
fix typo in ParserInternalState
jtattermusch May 28, 2020
fe14799
progress: stuff almost builds now
jtattermusch May 28, 2020
f9d9019
more progress
jtattermusch May 28, 2020
ee6b20a
CodedOutputStream adjustments
jtattermusch May 28, 2020
d0e08f5
entire solution builds now
jtattermusch May 28, 2020
5fc49bd
fix a bunch of bugs
jtattermusch May 28, 2020
5742a64
fix WriteString bug
jtattermusch May 28, 2020
c17af44
apply SecuritySafeCritical attribute
jtattermusch May 29, 2020
ca7bc46
make all writing use WriteContext
jtattermusch May 29, 2020
dda6217
codegen for WriteContext based serialization
jtattermusch May 29, 2020
d3eddf7
make everything build, with some TODOs
jtattermusch May 29, 2020
125e4ad
regenerate C# protos
jtattermusch May 29, 2020
ea1d559
test are almost passing
jtattermusch May 29, 2020
2b9a73e
fix codegen
jtattermusch May 29, 2020
9070389
regenerate code
jtattermusch May 29, 2020
361c933
annotate ByteString.Span and ByteString.Memory as SecuritySafeCritical
jtattermusch May 29, 2020
90d4969
LegacyGeneratedCodeTest now passing
jtattermusch May 29, 2020
3cdc107
fix bug in RefreshBuffer
jtattermusch Jun 3, 2020
ecbb29d
add WriteContext.Flush() method
jtattermusch Jun 3, 2020
2bce090
add more tests
jtattermusch Jun 3, 2020
1e1d455
add WriteFloat TODO
jtattermusch Jun 3, 2020
8dbf707
add more tests
jtattermusch Jun 3, 2020
9039103
message extensions + refactor
jtattermusch Jun 3, 2020
7bfaaba
cleanup coded output stream
jtattermusch Jun 3, 2020
b3cdba1
increase test coverage
jtattermusch Jun 3, 2020
ba61d76
simplify serialization to single span
jtattermusch Jun 3, 2020
94e64f2
a bit more cleanup
jtattermusch Jun 3, 2020
f9f92a6
increase test coverage
jtattermusch Jun 3, 2020
5637289
test writing with different blocksizes
jtattermusch Jun 3, 2020
b2c9497
remove a TODO
jtattermusch Jun 3, 2020
886c263
initial version of write benchmarks
jtattermusch Jun 5, 2020
a296413
optimize WriteFloat
jtattermusch Jun 5, 2020
8a2d588
address review comments
jtattermusch Jun 8, 2020
3dad187
add benchmark for writing of NonAsciiStrings
jtattermusch Jun 8, 2020
3375e25
optimize writing non-ascii strings
jtattermusch Jun 8, 2020
43dcee2
remove some todos
jtattermusch Jun 8, 2020
e14a5c8
address a few TODOs
jtattermusch Jun 8, 2020
53708e2
test writing to a stackalloc buffer
jtattermusch Jun 8, 2020
19c0d73
test WriteContext writing with multiple flushes
jtattermusch Jun 8, 2020
c06812b
address a few TODOs
jtattermusch Jun 8, 2020
e346fde
remove commented out code
jtattermusch Jun 8, 2020
5eec497
fix C# CompatibilityTests
jtattermusch Jun 9, 2020
549dc9a
optimize writing fixed32 and fixed64, fix benchmark
jtattermusch Jun 9, 2020
2350e90
add new C# files to Makefile.am
jtattermusch Jun 9, 2020
6a69690
basic version of WriteMessagesBenchmark
jtattermusch Jun 10, 2020
e967fac
update Makefile.am
jtattermusch Jun 11, 2020
9d6969b
Merge remote-tracking branch 'upstream/master' into protobuf_buffer_s…
jtattermusch Jun 11, 2020
468c3ba
Speed up writing of messages with many fields
jtattermusch Jun 12, 2020
1f56e5e
remove AggressiveInlining attribute from WritingPrimitives.cs
jtattermusch Jun 23, 2020
d3557ca
WriteFloat improvements
jtattermusch Jun 23, 2020
17a4b18
optimize WriteString
jtattermusch Jun 23, 2020
6afd469
optimize WriteFixed32 and WriteFixed64
jtattermusch Jun 23, 2020
80780bd
optimize WriteRawByte
jtattermusch Jun 23, 2020
9ca0877
optimize WriteRawBytes
jtattermusch Jun 23, 2020
9d53fad
optimize WriteVarint32
jtattermusch Jun 23, 2020
2f16981
optimize WriteVarint64
jtattermusch Jun 23, 2020
4f0afc7
optimize WriteRawTag
jtattermusch Jun 23, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 8 additions & 0 deletions Makefile.am
Expand Up @@ -96,11 +96,14 @@ csharp_EXTRA_DIST= \
csharp/src/Google.Protobuf.Benchmarks/Program.cs \
csharp/src/Google.Protobuf.Benchmarks/wrapper_benchmark_messages.proto \
csharp/src/Google.Protobuf.Benchmarks/WrapperBenchmarkMessages.cs \
csharp/src/Google.Protobuf.Benchmarks/WriteMessagesBenchmark.cs \
csharp/src/Google.Protobuf.Benchmarks/WriteRawPrimitivesBenchmark.cs \
csharp/src/Google.Protobuf.Conformance/Conformance.cs \
csharp/src/Google.Protobuf.Conformance/Google.Protobuf.Conformance.csproj \
csharp/src/Google.Protobuf.Conformance/Program.cs \
csharp/src/Google.Protobuf.JsonDump/Google.Protobuf.JsonDump.csproj \
csharp/src/Google.Protobuf.JsonDump/Program.cs \
csharp/src/Google.Protobuf.Test/Buffers/ArrayBufferWriter.cs \
csharp/src/Google.Protobuf.Test/ByteStringTest.cs \
csharp/src/Google.Protobuf.Test/CodedInputStreamExtensions.cs \
csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs \
Expand Down Expand Up @@ -259,6 +262,11 @@ csharp_EXTRA_DIST= \
csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs \
csharp/src/Google.Protobuf/WellKnownTypes/WrappersPartial.cs \
csharp/src/Google.Protobuf/WireFormat.cs \
csharp/src/Google.Protobuf/WritingPrimitivesMessages.cs \
csharp/src/Google.Protobuf/WritingPrimitives.cs \
csharp/src/Google.Protobuf/WriterInternalState.cs \
csharp/src/Google.Protobuf/WriteContext.cs \
csharp/src/Google.Protobuf/WriteBufferHelper.cs \
csharp/src/Google.Protobuf/UnknownField.cs \
csharp/src/Google.Protobuf/UnknownFieldSet.cs

Expand Down
Expand Up @@ -211,62 +211,62 @@ public void WriteWholeMessage_VaryingBlockSizes()
[Test]
public void EncodeZigZag32()
{
Assert.AreEqual(0u, CodedOutputStream.EncodeZigZag32(0));
Assert.AreEqual(1u, CodedOutputStream.EncodeZigZag32(-1));
Assert.AreEqual(2u, CodedOutputStream.EncodeZigZag32(1));
Assert.AreEqual(3u, CodedOutputStream.EncodeZigZag32(-2));
Assert.AreEqual(0x7FFFFFFEu, CodedOutputStream.EncodeZigZag32(0x3FFFFFFF));
Assert.AreEqual(0x7FFFFFFFu, CodedOutputStream.EncodeZigZag32(unchecked((int) 0xC0000000)));
Assert.AreEqual(0xFFFFFFFEu, CodedOutputStream.EncodeZigZag32(0x7FFFFFFF));
Assert.AreEqual(0xFFFFFFFFu, CodedOutputStream.EncodeZigZag32(unchecked((int) 0x80000000)));
Assert.AreEqual(0u, WritingPrimitives.EncodeZigZag32(0));
Assert.AreEqual(1u, WritingPrimitives.EncodeZigZag32(-1));
Assert.AreEqual(2u, WritingPrimitives.EncodeZigZag32(1));
Assert.AreEqual(3u, WritingPrimitives.EncodeZigZag32(-2));
Assert.AreEqual(0x7FFFFFFEu, WritingPrimitives.EncodeZigZag32(0x3FFFFFFF));
Assert.AreEqual(0x7FFFFFFFu, WritingPrimitives.EncodeZigZag32(unchecked((int) 0xC0000000)));
Assert.AreEqual(0xFFFFFFFEu, WritingPrimitives.EncodeZigZag32(0x7FFFFFFF));
Assert.AreEqual(0xFFFFFFFFu, WritingPrimitives.EncodeZigZag32(unchecked((int) 0x80000000)));
}

[Test]
public void EncodeZigZag64()
{
Assert.AreEqual(0u, CodedOutputStream.EncodeZigZag64(0));
Assert.AreEqual(1u, CodedOutputStream.EncodeZigZag64(-1));
Assert.AreEqual(2u, CodedOutputStream.EncodeZigZag64(1));
Assert.AreEqual(3u, CodedOutputStream.EncodeZigZag64(-2));
Assert.AreEqual(0u, WritingPrimitives.EncodeZigZag64(0));
Assert.AreEqual(1u, WritingPrimitives.EncodeZigZag64(-1));
Assert.AreEqual(2u, WritingPrimitives.EncodeZigZag64(1));
Assert.AreEqual(3u, WritingPrimitives.EncodeZigZag64(-2));
Assert.AreEqual(0x000000007FFFFFFEuL,
CodedOutputStream.EncodeZigZag64(unchecked((long) 0x000000003FFFFFFFUL)));
WritingPrimitives.EncodeZigZag64(unchecked((long) 0x000000003FFFFFFFUL)));
Assert.AreEqual(0x000000007FFFFFFFuL,
CodedOutputStream.EncodeZigZag64(unchecked((long) 0xFFFFFFFFC0000000UL)));
WritingPrimitives.EncodeZigZag64(unchecked((long) 0xFFFFFFFFC0000000UL)));
Assert.AreEqual(0x00000000FFFFFFFEuL,
CodedOutputStream.EncodeZigZag64(unchecked((long) 0x000000007FFFFFFFUL)));
WritingPrimitives.EncodeZigZag64(unchecked((long) 0x000000007FFFFFFFUL)));
Assert.AreEqual(0x00000000FFFFFFFFuL,
CodedOutputStream.EncodeZigZag64(unchecked((long) 0xFFFFFFFF80000000UL)));
WritingPrimitives.EncodeZigZag64(unchecked((long) 0xFFFFFFFF80000000UL)));
Assert.AreEqual(0xFFFFFFFFFFFFFFFEL,
CodedOutputStream.EncodeZigZag64(unchecked((long) 0x7FFFFFFFFFFFFFFFUL)));
WritingPrimitives.EncodeZigZag64(unchecked((long) 0x7FFFFFFFFFFFFFFFUL)));
Assert.AreEqual(0xFFFFFFFFFFFFFFFFL,
CodedOutputStream.EncodeZigZag64(unchecked((long) 0x8000000000000000UL)));
WritingPrimitives.EncodeZigZag64(unchecked((long) 0x8000000000000000UL)));
}

[Test]
public void RoundTripZigZag32()
{
// Some easier-to-verify round-trip tests. The inputs (other than 0, 1, -1)
// were chosen semi-randomly via keyboard bashing.
Assert.AreEqual(0, ParsingPrimitives.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(0)));
Assert.AreEqual(1, ParsingPrimitives.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(1)));
Assert.AreEqual(-1, ParsingPrimitives.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(-1)));
Assert.AreEqual(14927, ParsingPrimitives.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(14927)));
Assert.AreEqual(-3612, ParsingPrimitives.DecodeZigZag32(CodedOutputStream.EncodeZigZag32(-3612)));
Assert.AreEqual(0, ParsingPrimitives.DecodeZigZag32(WritingPrimitives.EncodeZigZag32(0)));
Assert.AreEqual(1, ParsingPrimitives.DecodeZigZag32(WritingPrimitives.EncodeZigZag32(1)));
Assert.AreEqual(-1, ParsingPrimitives.DecodeZigZag32(WritingPrimitives.EncodeZigZag32(-1)));
Assert.AreEqual(14927, ParsingPrimitives.DecodeZigZag32(WritingPrimitives.EncodeZigZag32(14927)));
Assert.AreEqual(-3612, ParsingPrimitives.DecodeZigZag32(WritingPrimitives.EncodeZigZag32(-3612)));
}

[Test]
public void RoundTripZigZag64()
{
Assert.AreEqual(0, ParsingPrimitives.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(0)));
Assert.AreEqual(1, ParsingPrimitives.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(1)));
Assert.AreEqual(-1, ParsingPrimitives.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(-1)));
Assert.AreEqual(14927, ParsingPrimitives.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(14927)));
Assert.AreEqual(-3612, ParsingPrimitives.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(-3612)));
Assert.AreEqual(0, ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(0)));
Assert.AreEqual(1, ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(1)));
Assert.AreEqual(-1, ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(-1)));
Assert.AreEqual(14927, ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(14927)));
Assert.AreEqual(-3612, ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(-3612)));

Assert.AreEqual(856912304801416L,
ParsingPrimitives.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(856912304801416L)));
ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(856912304801416L)));
Assert.AreEqual(-75123905439571256L,
ParsingPrimitives.DecodeZigZag64(CodedOutputStream.EncodeZigZag64(-75123905439571256L)));
ParsingPrimitives.DecodeZigZag64(WritingPrimitives.EncodeZigZag64(-75123905439571256L)));
}

[Test]
Expand Down Expand Up @@ -395,7 +395,7 @@ public void Dispose_DisposesUnderlyingStream()
Assert.IsTrue(memoryStream.CanWrite);
using (var cos = new CodedOutputStream(memoryStream))
{
cos.WriteRawByte(0);
cos.WriteRawBytes(new byte[] {0});
Assert.AreEqual(0, memoryStream.Position); // Not flushed yet
}
Assert.AreEqual(1, memoryStream.ToArray().Length); // Flushed data from CodedOutputStream to MemoryStream
Expand All @@ -409,7 +409,7 @@ public void Dispose_WithLeaveOpen()
Assert.IsTrue(memoryStream.CanWrite);
using (var cos = new CodedOutputStream(memoryStream, true))
{
cos.WriteRawByte(0);
cos.WriteRawBytes(new byte[] {0});
Assert.AreEqual(0, memoryStream.Position); // Not flushed yet
}
Assert.AreEqual(1, memoryStream.Position); // Flushed data from CodedOutputStream to MemoryStream
Expand Down
Expand Up @@ -124,7 +124,16 @@ public void TestRoundTripRaw()
{
var stream = new MemoryStream();
var codedOutput = new CodedOutputStream(stream);
codec.ValueWriter(codedOutput, sampleValue);
WriteContext.Initialize(codedOutput, out WriteContext ctx);
try
{
// only write the value using the codec
codec.ValueWriter(ref ctx, sampleValue);
}
finally
{
ctx.CopyStateTo(codedOutput);
}
codedOutput.Flush();
stream.Position = 0;
var codedInput = new CodedInputStream(stream);
Expand Down Expand Up @@ -172,7 +181,16 @@ public void TestDefaultValue()
if (codec.DefaultValue != null) // This part isn't appropriate for message types.
{
codedOutput = new CodedOutputStream(stream);
codec.ValueWriter(codedOutput, codec.DefaultValue);
WriteContext.Initialize(codedOutput, out WriteContext ctx);
try
{
// only write the value using the codec
codec.ValueWriter(ref ctx, codec.DefaultValue);
}
finally
{
ctx.CopyStateTo(codedOutput);
}
codedOutput.Flush();
Assert.AreNotEqual(0, stream.Position);
Assert.AreEqual(stream.Position, codec.ValueSizeCalculator(codec.DefaultValue));
Expand Down
65 changes: 65 additions & 0 deletions csharp/src/AddressBook/Addressbook.cs
Expand Up @@ -190,6 +190,9 @@ public sealed partial class Person : pb::IMessage<Person>

[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void WriteTo(pb::CodedOutputStream output) {
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
output.WriteRawMessage(this);
#else
if (Name.Length != 0) {
output.WriteRawTag(10);
output.WriteString(Name);
Expand All @@ -210,8 +213,35 @@ public sealed partial class Person : pb::IMessage<Person>
if (_unknownFields != null) {
_unknownFields.WriteTo(output);
}
#endif
}

#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
if (Name.Length != 0) {
output.WriteRawTag(10);
output.WriteString(Name);
}
if (Id != 0) {
output.WriteRawTag(16);
output.WriteInt32(Id);
}
if (Email.Length != 0) {
output.WriteRawTag(26);
output.WriteString(Email);
}
phones_.WriteTo(ref output, _repeated_phones_codec);
if (lastUpdated_ != null) {
output.WriteRawTag(42);
output.WriteMessage(LastUpdated);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(ref output);
}
}
#endif

[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int CalculateSize() {
int size = 0;
Expand Down Expand Up @@ -441,6 +471,9 @@ public sealed partial class PhoneNumber : pb::IMessage<PhoneNumber>

[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void WriteTo(pb::CodedOutputStream output) {
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
output.WriteRawMessage(this);
#else
if (Number.Length != 0) {
output.WriteRawTag(10);
output.WriteString(Number);
Expand All @@ -452,8 +485,26 @@ public sealed partial class PhoneNumber : pb::IMessage<PhoneNumber>
if (_unknownFields != null) {
_unknownFields.WriteTo(output);
}
#endif
}

#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
if (Number.Length != 0) {
output.WriteRawTag(10);
output.WriteString(Number);
}
if (Type != global::Google.Protobuf.Examples.AddressBook.Person.Types.PhoneType.Mobile) {
output.WriteRawTag(16);
output.WriteEnum((int) Type);
}
if (_unknownFields != null) {
_unknownFields.WriteTo(ref output);
}
}
#endif

[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int CalculateSize() {
int size = 0;
Expand Down Expand Up @@ -621,12 +672,26 @@ public sealed partial class AddressBook : pb::IMessage<AddressBook>

[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public void WriteTo(pb::CodedOutputStream output) {
#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
output.WriteRawMessage(this);
#else
people_.WriteTo(output, _repeated_people_codec);
if (_unknownFields != null) {
_unknownFields.WriteTo(output);
}
#endif
}

#if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
void pb::IBufferMessage.InternalWriteTo(ref pb::WriteContext output) {
people_.WriteTo(ref output, _repeated_people_codec);
if (_unknownFields != null) {
_unknownFields.WriteTo(ref output);
}
}
#endif

[global::System.Diagnostics.DebuggerNonUserCodeAttribute]
public int CalculateSize() {
int size = 0;
Expand Down