awr / KafkaClient

Native C# client for Kafka
Apache License 2.0
5 stars 2 forks source link

Improve performance for ProduceRequest and FetchResponse #20

Closed awr closed 7 years ago

awr commented 7 years ago

A dependent of #16

Encoding of ProduceRequest

Using random, consistent message bytes.


BenchmarkDotNet=v0.10.1, OS=Windows
Processor=?, ProcessorCount=8
Frequency=2435767 Hz, Resolution=410.5483 ns, Timer=TSC
dotnet cli version=1.0.0-preview2-1-003177
  [Host]     : .NET Core 4.6.24628.01, 64bit RyuJIT
  DefaultJob : .NET Core 4.6.24628.01, 64bit RyuJIT

Benchmark Baseline (CodecNone)

Note that speed is important, but so is memory allocation and byte size. Byte size will directly impact network traffic costs (especially in terms of overall speed).

Method Messages MessageSize Codec Mean StdDev Gen 0 Gen 1 Gen 2 Allocated
Encode 100 1 CodecNone 82.9727 us 0.8513 us 7.4056 - - 63.63 kB
Encode 100 1000 CodecNone 1,211.5400 us 9.5125 us 31.7708 31.7708 31.7708 429.46 kB
Encode 10000 1 CodecNone 8,695.0426 us 46.7663 us 702.0833 47.9167 45.8333 6.43 MB
Encode 10000 1000 CodecNone 131,300.6830 us 845.3136 us 1454.1667 641.6667 641.6667 46.84 MB
Codec Level Messages MessageSize Bytes
CodecNone - 100 1 2746
CodecNone - 100 1000 102646
CodecNone - 10000 1 270046
CodecNone - 10000 1000 10260046
CodecGzip Fastest 100 1 147
CodecGzip Optimal 100 1 132
CodecGzip Fastest 100 1000 2272
CodecGzip Optimal 100 1000 1816
CodecGzip Fastest 10000 1 1718
CodecGzip Optimal 10000 1 782
CodecGzip Fastest 10000 1000 100861
CodecGzip Optimal 10000 1000 56002

Benchmark Gzip (CodecGzip with byte[])

Method Messages MessageSize Codec Level Mean StdDev Gen 0 Gen 1 Gen 2 Allocated
Encode 100 1 CodecGzip Fastest 108.3579 us 0.5767 us 7.0313 - - 73.96 kB
Encode 100 1 CodecGzip Optimal 103.9860 us 0.2018 us 7.0313 - - 73.94 kB
Encode 100 1000 CodecGzip Fastest 1,304.7041 us 9.7604 us 33.8542 33.8542 33.8542 442.34 kB
Encode 100 1000 CodecGzip Optimal 1,331.5181 us 8.1201 us 36.9792 36.9792 36.9792 442.37 kB
Encode 10000 1 CodecGzip Fastest 8,978.8525 us 78.0883 us 710.4167 56.2500 54.1667 6.45 MB
Encode 10000 1 CodecGzip Optimal 8,897.3779 us 88.5309 us 718.7500 64.5833 62.5000 6.45 MB
Encode 10000 1000 CodecGzip Fastest 133,817.3749 us 1,517.0871 us 1075.0000 262.5000 262.5000 45.02 MB
Encode 10000 1000 CodecGzip Optimal 138,365.5674 us 305.4618 us 1104.1667 291.6667 291.6667 46.15 MB

Benchmark Gzip (CodecGzip with Stream)

Method Messages MessageSize Codec Level Mean StdDev Gen 0 Gen 1 Gen 2 Allocated
Encode 100 1 CodecGzip Fastest 108.4666 us 1.6359 us 6.2826 - - 73.51 kB
Encode 100 1 CodecGzip Optimal 108.6534 us 1.1747 us 6.5430 - - 73.51 kB
Encode 100 1000 CodecGzip Fastest 1,291.8933 us 21.6539 us 32.8125 32.8125 32.8125 437.78 kB
Encode 100 1000 CodecGzip Optimal 1,288.3538 us 9.6701 us 33.8542 33.8542 33.8542 437.78 kB
Encode 10000 1 CodecGzip Fastest 8,635.0205 us 74.1442 us 718.7500 64.5833 62.5000 6.44 MB
Encode 10000 1 CodecGzip Optimal 8,621.5494 us 82.3327 us 677.0833 22.9167 20.8333 6.44 MB
Encode 10000 1000 CodecGzip Fastest 137,845.2882 us 5,184.4836 us 1158.3333 345.8333 345.8333 44.82 MB
Encode 10000 1000 CodecGzip Optimal 137,451.9864 us 1,243.2845 us 1187.5000 375.0000 375.0000 45.72 MB

The stream approach seems to be marginally better for memory allocation (consistent across runs), with timing in the same ballpark (varying across runs). I'm going to opt for the streaming approach.

The level isn't quite as clear -- it appears that Optimal is likely worth using, but I'd like to see what happens when unzipping first.

awr commented 7 years ago

Decoding of FetchResponse

Benchmark Baseline

Codec Level Messages MessageSize Bytes
CodecNone - 100 1 2741
CodecNone - 100 1000 102641
CodecNone - 10000 1 270041
CodecNone - 10000 1000 10260041
CodecGzip Fastest 100 1 142
CodecGzip Optimal 100 1 127
CodecGzip Fastest 100 1000 2268
CodecGzip Optimal 100 1000 1810
CodecGzip Fastest 10000 1 1712
CodecGzip Optimal 10000 1 776
CodecGzip Fastest 10000 1000 100841
CodecGzip Optimal 10000 1000 55998
Method Messages MessageSize Codec Level Mean StdDev Gen 0 Gen 1 Gen 2 Allocated
Encode 100 1 CodecNone - 87.0268 us 1.9190 us 12.9720 - - 97.51 kB
Encode 100 1000 CodecNone - 375.9477 us 2.2836 us 37.5000 1.3672 - 296.14 kB
Encode 10000 1 CodecNone - 16,755.5257 us 208.9175 us 1500.0000 - - 12.78 MB
Encode 10000 1000 CodecNone - 63,380.1783 us 1,243.1818 us 5212.5000 1337.5000 25.0000 32.64 MB

Benchmark Gzip (CodecGzip)

Method Messages MessageSize Codec Level Mean StdDev Gen 0 Gen 1 Gen 2 Allocated
Encode 100 1 CodecGzip Fastest 104.1415 us 5.0871 us 25.4557 - - 191.97 kB
Encode 100 1 CodecGzip Optimal 99.7615 us 0.6994 us 24.9349 - - 191.98 kB
Encode 100 1000 CodecGzip Fastest 624.4121 us 4.4350 us 78.9063 30.0781 30.0781 636.1 kB
Encode 100 1000 CodecGzip Optimal 612.5113 us 5.6414 us 80.4688 31.6406 31.6406 636.05 kB
Encode 10000 1 CodecGzip Fastest 15,290.6637 us 309.8344 us 1495.8333 120.8333 - 13.44 MB
Encode 10000 1 CodecGzip Optimal 15,162.5197 us 230.7732 us 1495.8333 120.8333 - 13.44 MB
Encode 10000 1000 CodecGzip Fastest 74,881.5758 us 188.8831 us 5637.5000 2262.5000 762.5000 48.49 MB
Encode 10000 1000 CodecGzip Optimal 76,642.1930 us 377.7283 us 5620.8333 2245.8333 745.8333 48.6 MB

The level looks to be about a wash -- it appears that Optimal has about half the bytes (better for network data transfer), so may be worth it. Better to leave it as an undocumented option, set to Optimal for now.

awr commented 7 years ago

Encoding of ProduceRequest

After adopting ArraySegment

Method Messages MessageSize Codec Level Mean StdDev Gen 0 Gen 1 Gen 2 Allocated
Encode 100 1 CodecGzip Fastest 117.4483 us 0.5271 us 6.2826 - - 70.64 kB
Encode 100 1 CodecGzip Optimal 113.0407 us 0.3224 us 6.5430 - - 70.64 kB
Encode 100 1000 CodecGzip Fastest 1,333.4242 us 6.0990 us 2.6042 2.6042 2.6042 332.57 kB
Encode 100 1000 CodecGzip Optimal 1,403.8961 us 49.4532 us 5.7292 5.7292 5.7292 332.85 kB
Encode 10000 1 CodecGzip Fastest 10,091.0709 us 43.4044 us 552.0833 - - 6.17 MB
Encode 10000 1 CodecGzip Optimal 9,359.1272 us 92.2271 us 593.7500 31.2500 31.2500 6.17 MB
Encode 10000 1000 CodecGzip Fastest 130,928.3806 us 1,135.4329 us 1225.0000 416.6667 412.5000 33.45 MB
Encode 10000 1000 CodecGzip Optimal 138,024.9768 us 1,518.3529 us 1291.6667 479.1667 479.1667 35.3 MB
awr commented 7 years ago

Encoding of ProduceRequest

After rewriting some of the BigEndian stuff, and making more use of ArraySegment (~1/2 overall time in all but the smallest scenarios, significantly less memory used)

Method Messages MessageSize Codec Level Mean StdDev Gen 0 Gen 1 Gen 2 Allocated
Encode 100 1 CodecGzip Fastest 72.3858 us 0.5691 us 6.0547 - - 56.05 kB
Encode 100 1 CodecGzip Optimal 68.1506 us 0.1522 us 6.3151 - - 56.05 kB
Encode 100 1000 CodecGzip Fastest 519.6534 us 3.8164 us 21.7448 21.7448 21.7448 317.91 kB
Encode 100 1000 CodecGzip Optimal 561.9916 us 15.2529 us 23.3073 23.3073 23.3073 318.22 kB
Encode 10000 1 CodecGzip Fastest 5,582.3816 us 53.8721 us 573.9583 152.0833 152.0833 4.73 MB
Encode 10000 1 CodecGzip Optimal 5,580.9517 us 77.2974 us 557.2917 135.4167 135.4167 4.73 MB
Encode 10000 1000 CodecGzip Fastest 53,369.4465 us 973.6416 us 1062.5000 437.5000 437.5000 31.32 MB
Encode 10000 1000 CodecGzip Optimal 56,977.1002 us 156.7376 us 933.3333 308.3333 308.3333 30.54 MB
awr commented 7 years ago

Decoding of FetchResponse

After rewriting KafkaReader/Writer to use ArraySegment top to bottom (~1/2 overall time the largest scenarios, significantly less memory used in all scenarios)

Method Messages MessageSize Codec Level Mean StdDev Gen 0 Gen 1 Gen 2 Allocated
Encode 100 1 CodecGzip Optimal 70.1029 us 0.7893 us 19.7428 0.2116 - 140.07 kB
Encode 100 1 CodecNone - 60.2857 us 1.6846 us 4.7852 - - 46.36 kB
Encode 100 1000 CodecGzip Optimal 545.7322 us 6.9165 us 30.0781 30.0781 30.0781 383.37 kB
Encode 100 1000 CodecNone - 319.5567 us 1.1314 us - - - 46.36 kB
Encode 10000 1 CodecGzip Optimal 10,891.6299 us 99.3798 us 991.6667 241.6667 - 8.42 MB
Encode 10000 1 CodecNone - 10,572.7410 us 112.2507 us 968.7500 - - 7.75 MB
Encode 10000 1000 CodecGzip Optimal 59,328.4874 us 155.3348 us 2012.5000 1387.5000 762.5000 23.5 MB
Encode 10000 1000 CodecNone - 37,065.9955 us 299.4796 us 604.1667 - - 7.75 MB