This is an automated email from the ASF dual-hosted git repository.
blankensteiner pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/pulsar-dotpulsar.git
The following commit(s) were added to refs/heads/master by this push:
new 5357829 Added compression benchmarks
5357829 is described below
commit 53578295ad9f2552f50f6e2b05c30171e274af6e
Author: Daniel Blankensteiner <[email protected]>
AuthorDate: Wed Feb 7 12:21:59 2024 +0100
Added compression benchmarks
---
DotPulsar.sln | 9 +++
benchmarks/Compression/Compress.cs | 69 +++++++++++++++++++++
benchmarks/Compression/Compression.csproj | 32 ++++++++++
benchmarks/Compression/Decompress.cs | 89 ++++++++++++++++++++++++++++
benchmarks/Compression/Factories.cs | 64 ++++++++++++++++++++
benchmarks/Compression/MessageBytes.cs | 76 ++++++++++++++++++++++++
benchmarks/Compression/MessageSize.cs | 21 +++++++
benchmarks/Compression/MessageType.cs | 21 +++++++
benchmarks/Compression/Messages.proto | 30 ++++++++++
benchmarks/Compression/Program.cs | 40 +++++++++++++
tests/DotPulsar.Tests/DotPulsar.Tests.csproj | 4 +-
11 files changed, 453 insertions(+), 2 deletions(-)
diff --git a/DotPulsar.sln b/DotPulsar.sln
index 35c2690..1706858 100644
--- a/DotPulsar.sln
+++ b/DotPulsar.sln
@@ -26,6 +26,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") =
"Solution Items", "Solution
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Processing",
"samples\Processing\Processing.csproj", "{CC1494FA-4EB5-4DB9-8BE9-0A6E8D0D963E}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Compression",
"benchmarks\Compression\Compression.csproj",
"{040F8253-074D-4977-BDB1-0D9798B52CE2}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Benchmarks",
"Benchmarks", "{2C57AF4B-0D23-42D7-86FE-80277FD52875}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -56,6 +60,10 @@ Global
{CC1494FA-4EB5-4DB9-8BE9-0A6E8D0D963E}.Debug|Any CPU.Build.0 =
Debug|Any CPU
{CC1494FA-4EB5-4DB9-8BE9-0A6E8D0D963E}.Release|Any
CPU.ActiveCfg = Release|Any CPU
{CC1494FA-4EB5-4DB9-8BE9-0A6E8D0D963E}.Release|Any CPU.Build.0
= Release|Any CPU
+ {040F8253-074D-4977-BDB1-0D9798B52CE2}.Debug|Any CPU.ActiveCfg
= Debug|Any CPU
+ {040F8253-074D-4977-BDB1-0D9798B52CE2}.Debug|Any CPU.Build.0 =
Debug|Any CPU
+ {040F8253-074D-4977-BDB1-0D9798B52CE2}.Release|Any
CPU.ActiveCfg = Release|Any CPU
+ {040F8253-074D-4977-BDB1-0D9798B52CE2}.Release|Any CPU.Build.0
= Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -66,6 +74,7 @@ Global
{14934BED-A222-47B2-A58A-CFC4AAB89B49} =
{E7106D0F-B255-4631-9FB8-734FC5748FA9}
{6D44683B-865C-4D15-9F0A-1A8441354589} =
{E7106D0F-B255-4631-9FB8-734FC5748FA9}
{CC1494FA-4EB5-4DB9-8BE9-0A6E8D0D963E} =
{E7106D0F-B255-4631-9FB8-734FC5748FA9}
+ {040F8253-074D-4977-BDB1-0D9798B52CE2} =
{2C57AF4B-0D23-42D7-86FE-80277FD52875}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {88355922-E70A-4B73-B7F8-ABF8F2B59789}
diff --git a/benchmarks/Compression/Compress.cs
b/benchmarks/Compression/Compress.cs
new file mode 100644
index 0000000..66b7b56
--- /dev/null
+++ b/benchmarks/Compression/Compress.cs
@@ -0,0 +1,69 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Compression;
+
+using BenchmarkDotNet.Attributes;
+using BenchmarkDotNet.Order;
+using System.Buffers;
+
+[RankColumn, Orderer(SummaryOrderPolicy.FastestToSlowest)]
+public class Compress
+{
+ [ParamsAllValues]
+ public MessageSize Size { get; set; }
+
+ [ParamsAllValues]
+ public MessageType Type { get; set; }
+
+ [GlobalSetup]
+ public void Setup() => Data = MessageBytes.GetBytes(Size, Type);
+
+ public ReadOnlySequence<byte> Data { get; private set; }
+
+ [Benchmark]
+ public void K4aosCompressionLz4()
+ {
+ using var compressor =
Factories.K4aosCompressionLz4CompressorFactory.Create();
+ _ = compressor.Compress(Data);
+ }
+
+ [Benchmark]
+ public void IronSnappy()
+ {
+ using var compressor = Factories.IronSnappyCompressorFactory.Create();
+ _ = compressor.Compress(Data);
+ }
+
+ [Benchmark]
+ public void DotNetZip()
+ {
+ using var compressor = Factories.DotNetZipCompressorFactory.Create();
+ _ = compressor.Compress(Data);
+ }
+
+ [Benchmark]
+ public void ZstdNet()
+ {
+ using var compressor = Factories.ZstdNetCompressorFactory.Create();
+ _ = compressor.Compress(Data);
+ }
+
+ [Benchmark]
+ public void ZstdSharp()
+ {
+ using var compressor = Factories.ZstdSharpCompressorFactory.Create();
+ _ = compressor.Compress(Data);
+ }
+}
diff --git a/benchmarks/Compression/Compression.csproj
b/benchmarks/Compression/Compression.csproj
new file mode 100644
index 0000000..288add9
--- /dev/null
+++ b/benchmarks/Compression/Compression.csproj
@@ -0,0 +1,32 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+ <PropertyGroup>
+ <OutputType>Exe</OutputType>
+ <TargetFramework>net8.0</TargetFramework>
+ <ImplicitUsings>enable</ImplicitUsings>
+ <Nullable>enable</Nullable>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <PackageReference Include="BenchmarkDotNet" Version="0.13.12" />
+ <PackageReference Include="DotNetZip" Version="1.16.0" />
+ <PackageReference Include="Google.Protobuf" Version="3.25.2" />
+ <PackageReference Include="Grpc.Tools" Version="2.61.0">
+ <PrivateAssets>all</PrivateAssets>
+ <IncludeAssets>runtime; build; native; contentfiles; analyzers;
buildtransitive</IncludeAssets>
+ </PackageReference>
+ <PackageReference Include="IronSnappy" Version="1.3.1" />
+ <PackageReference Include="K4os.Compression.LZ4" Version="1.3.6" />
+ <PackageReference Include="ZstdNet" Version="1.4.5" />
+ <PackageReference Include="ZstdSharp.Port" Version="0.7.5" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <Protobuf Include="Messages.proto" GrpcServices="None" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <ProjectReference Include="..\..\src\DotPulsar\DotPulsar.csproj" />
+ </ItemGroup>
+
+</Project>
diff --git a/benchmarks/Compression/Decompress.cs
b/benchmarks/Compression/Decompress.cs
new file mode 100644
index 0000000..902511a
--- /dev/null
+++ b/benchmarks/Compression/Decompress.cs
@@ -0,0 +1,89 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Compression;
+
+using BenchmarkDotNet.Attributes;
+using BenchmarkDotNet.Order;
+using System.Buffers;
+
+[RankColumn, Orderer(SummaryOrderPolicy.FastestToSlowest)]
+public class Decompress
+{
+ [ParamsAllValues]
+ public MessageSize Size { get; set; }
+
+ [ParamsAllValues]
+ public MessageType Type { get; set; }
+
+ [GlobalSetup]
+ public void Setup()
+ {
+ var data = MessageBytes.GetBytes(Size, Type);
+ DecompressedSize = (int) data.Length;
+
+ using (var compressor =
Factories.K4aosCompressionLz4CompressorFactory.Create())
+ K4aosCompressionLz4Data = compressor.Compress(data);
+ using (var compressor = Factories.IronSnappyCompressorFactory.Create())
+ IronSnappyData = compressor.Compress(data);
+ using (var compressor = Factories.DotNetZipCompressorFactory.Create())
+ DotNetZipData = compressor.Compress(data);
+ using (var compressor = Factories.ZstdNetCompressorFactory.Create())
+ ZstdNetData = compressor.Compress(data);
+ using (var compressor = Factories.ZstdSharpCompressorFactory.Create())
+ ZstdSharpData = compressor.Compress(data);
+ }
+
+ public int DecompressedSize { get; private set; }
+ public ReadOnlySequence<byte> K4aosCompressionLz4Data { get; private set; }
+ public ReadOnlySequence<byte> IronSnappyData { get; private set; }
+ public ReadOnlySequence<byte> DotNetZipData { get; private set; }
+ public ReadOnlySequence<byte> ZstdNetData { get; private set; }
+ public ReadOnlySequence<byte> ZstdSharpData { get; private set; }
+
+ [Benchmark]
+ public void K4aosCompressionLz4()
+ {
+ using var decompressor =
Factories.K4aosCompressionLz4DecompressorFactory.Create();
+ _ = decompressor.Decompress(K4aosCompressionLz4Data, DecompressedSize);
+ }
+
+ [Benchmark]
+ public void IronSnappy()
+ {
+ using var decompressor =
Factories.IronSnappyDecompressorFactory.Create();
+ _ = decompressor.Decompress(IronSnappyData, DecompressedSize);
+ }
+
+ [Benchmark]
+ public void DotNetZip()
+ {
+ using var decompressor =
Factories.DotNetZipDecompressorFactory.Create();
+ _ = decompressor.Decompress(DotNetZipData, DecompressedSize);
+ }
+
+ [Benchmark]
+ public void ZstdNet()
+ {
+ using var decompressor = Factories.ZstdNetDecompressorFactory.Create();
+ _ = decompressor.Decompress(ZstdNetData, DecompressedSize);
+ }
+
+ [Benchmark]
+ public void ZstdSharp()
+ {
+ using var decompressor =
Factories.ZstdSharpDecompressorFactory.Create();
+ _ = decompressor.Decompress(ZstdSharpData, DecompressedSize);
+ }
+}
diff --git a/benchmarks/Compression/Factories.cs
b/benchmarks/Compression/Factories.cs
new file mode 100644
index 0000000..045e377
--- /dev/null
+++ b/benchmarks/Compression/Factories.cs
@@ -0,0 +1,64 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Compression;
+
+using DotPulsar.Internal.Abstractions;
+using DotPulsar.Internal.Compression;
+
+public static class Factories
+{
+ static Factories()
+ {
+ if (!Lz4Compression.TryLoading(out var compressor, out var
decompressor))
+ throw new Exception("Could not load K4os.Compression.LZ4");
+ K4aosCompressionLz4CompressorFactory = compressor!;
+ K4aosCompressionLz4DecompressorFactory = decompressor!;
+
+ if (!SnappyCompression.TryLoading(out compressor, out decompressor))
+ throw new Exception("Could not load IronSnappy");
+ IronSnappyCompressorFactory = compressor!;
+ IronSnappyDecompressorFactory = decompressor!;
+
+ if (!ZlibCompression.TryLoading(out compressor, out decompressor))
+ throw new Exception("Could not load DotNetZip");
+ DotNetZipCompressorFactory = compressor!;
+ DotNetZipDecompressorFactory = decompressor!;
+
+ if (!ZstdCompression.TryLoading(out compressor, out decompressor))
+ throw new Exception("Could not load ZstdNet");
+ ZstdNetCompressorFactory = compressor!;
+ ZstdNetDecompressorFactory = decompressor!;
+
+ if (!ZstdSharpCompression.TryLoading(out compressor, out decompressor))
+ throw new Exception("Could not load ZstdSharp");
+ ZstdSharpCompressorFactory = compressor!;
+ ZstdSharpDecompressorFactory = decompressor!;
+ }
+
+ public static ICompressorFactory K4aosCompressionLz4CompressorFactory {
get; }
+ public static IDecompressorFactory K4aosCompressionLz4DecompressorFactory
{ get; }
+
+ public static ICompressorFactory IronSnappyCompressorFactory { get; }
+ public static IDecompressorFactory IronSnappyDecompressorFactory { get; }
+
+ public static ICompressorFactory DotNetZipCompressorFactory { get; }
+ public static IDecompressorFactory DotNetZipDecompressorFactory { get; }
+
+ public static ICompressorFactory ZstdNetCompressorFactory { get; }
+ public static IDecompressorFactory ZstdNetDecompressorFactory { get; }
+
+ public static ICompressorFactory ZstdSharpCompressorFactory { get; }
+ public static IDecompressorFactory ZstdSharpDecompressorFactory { get; }
+}
diff --git a/benchmarks/Compression/MessageBytes.cs
b/benchmarks/Compression/MessageBytes.cs
new file mode 100644
index 0000000..7124e5f
--- /dev/null
+++ b/benchmarks/Compression/MessageBytes.cs
@@ -0,0 +1,76 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Compression;
+
+using Compression.Messages;
+using Google.Protobuf;
+using Google.Protobuf.WellKnownTypes;
+using System.Buffers;
+using System.Text;
+
+public static class MessageBytes
+{
+ static MessageBytes()
+ {
+ var smallMessage = CreateMessage(1024); //1KB
+ SmallProtobufMessageBytes = new
ReadOnlySequence<byte>(smallMessage.ToByteArray());
+ SmallJsonMessageBytes = new
ReadOnlySequence<byte>(Encoding.UTF8.GetBytes(JsonFormatter.Default.Format(smallMessage)));
+
+ var largeMessage = CreateMessage(1024*1024); //1MB
+ LargeProtobufMessageBytes = new
ReadOnlySequence<byte>(largeMessage.ToByteArray());
+ LargeJsonMessageBytes = new
ReadOnlySequence<byte>(Encoding.UTF8.GetBytes(JsonFormatter.Default.Format(largeMessage)));
+ }
+
+ public static ReadOnlySequence<byte> SmallProtobufMessageBytes { get; }
+ public static ReadOnlySequence<byte> LargeProtobufMessageBytes { get; }
+ public static ReadOnlySequence<byte> SmallJsonMessageBytes { get; }
+ public static ReadOnlySequence<byte> LargeJsonMessageBytes { get; }
+
+ public static ReadOnlySequence<byte> GetBytes(MessageSize messageSize,
MessageType messageType)
+ {
+ if (messageSize == MessageSize.Small && messageType ==
MessageType.Protobuf)
+ return SmallProtobufMessageBytes;
+ if (messageSize == MessageSize.Large && messageType ==
MessageType.Protobuf)
+ return LargeProtobufMessageBytes;
+ if (messageSize == MessageSize.Small && messageType ==
MessageType.Json)
+ return SmallJsonMessageBytes;
+ return LargeJsonMessageBytes;
+ }
+
+ private static Message CreateMessage(int minimumByteSize)
+ {
+ var message = new Message()
+ {
+ Pi = 3.14159265359,
+ IsTrue = true,
+ OneHour = TimeSpan.FromHours(1).ToDuration(),
+ Now = DateTime.UtcNow.ToTimestamp(),
+ };
+
+ while (message.CalculateSize() < minimumByteSize)
+ {
+ var innerMessage = new InnerMessage
+ {
+ MyEnum = InnerMessage.Types.Enum.Five,
+ NewGuid = Guid.NewGuid().ToString("N"),
+ RandomNumber = Random.Shared.Next()
+ };
+
+ message.InnerMessages.Add(innerMessage);
+ }
+
+ return message;
+ }
+}
diff --git a/benchmarks/Compression/MessageSize.cs
b/benchmarks/Compression/MessageSize.cs
new file mode 100644
index 0000000..2f4d88f
--- /dev/null
+++ b/benchmarks/Compression/MessageSize.cs
@@ -0,0 +1,21 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Compression;
+
+public enum MessageSize
+{
+ Small = 0,
+ Large = 1
+}
diff --git a/benchmarks/Compression/MessageType.cs
b/benchmarks/Compression/MessageType.cs
new file mode 100644
index 0000000..1919bad
--- /dev/null
+++ b/benchmarks/Compression/MessageType.cs
@@ -0,0 +1,21 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+namespace Compression;
+
+public enum MessageType
+{
+ Protobuf = 0,
+ Json = 1
+}
diff --git a/benchmarks/Compression/Messages.proto
b/benchmarks/Compression/Messages.proto
new file mode 100644
index 0000000..95a2f69
--- /dev/null
+++ b/benchmarks/Compression/Messages.proto
@@ -0,0 +1,30 @@
+syntax = "proto3";
+
+option csharp_namespace = "Compression.Messages";
+
+package compression.Messages;
+
+import "google/protobuf/duration.proto";
+import "google/protobuf/timestamp.proto";
+
+message Message {
+ double pi = 1;
+ bool is_true = 2;
+ google.protobuf.Duration one_hour = 3;
+ google.protobuf.Timestamp now = 4;
+ repeated InnerMessage inner_messages = 5;
+}
+
+message InnerMessage {
+ enum Enum {
+ ENUM_UNSPECIFIED = 0;
+ ENUM_ONE = 1;
+ ENUM_TWO = 2;
+ ENUM_THREE = 3;
+ ENUM_FOUR = 4;
+ ENUM_FIVE = 5;
+ }
+ Enum my_enum = 1;
+ int32 random_number = 2;
+ string new_guid = 3;
+}
diff --git a/benchmarks/Compression/Program.cs
b/benchmarks/Compression/Program.cs
new file mode 100644
index 0000000..1b91426
--- /dev/null
+++ b/benchmarks/Compression/Program.cs
@@ -0,0 +1,40 @@
+/*
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using BenchmarkDotNet.Running;
+using Compression;
+
+OutputCompressionInfo(MessageSize.Small, MessageType.Protobuf);
+OutputCompressionInfo(MessageSize.Large, MessageType.Protobuf);
+OutputCompressionInfo(MessageSize.Small, MessageType.Json);
+OutputCompressionInfo(MessageSize.Large, MessageType.Json);
+
+BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args);
+
+static void OutputCompressionInfo(MessageSize size, MessageType type)
+{
+ var data = MessageBytes.GetBytes(size, type);
+ Console.WriteLine($"{size} {type} message. Uncompressed size:
{data.Length}");
+
+ using (var compressor =
Factories.K4aosCompressionLz4CompressorFactory.Create())
+ Console.WriteLine($"\tCompressed with K4os.Compression.LZ4:
{compressor.Compress(data).Length}");
+ using (var compressor = Factories.IronSnappyCompressorFactory.Create())
+ Console.WriteLine($"\tCompressed with IronSnappy:
{compressor.Compress(data).Length}");
+ using (var compressor = Factories.DotNetZipCompressorFactory.Create())
+ Console.WriteLine($"\tCompressed with DotNetZip:
{compressor.Compress(data).Length}");
+ using (var compressor = Factories.ZstdNetCompressorFactory.Create())
+ Console.WriteLine($"\tCompressed with ZstdNet:
{compressor.Compress(data).Length}");
+ using (var compressor = Factories.ZstdSharpCompressorFactory.Create())
+ Console.WriteLine($"\tCompressed with ZstdSharp.Port:
{compressor.Compress(data).Length}");
+}
diff --git a/tests/DotPulsar.Tests/DotPulsar.Tests.csproj
b/tests/DotPulsar.Tests/DotPulsar.Tests.csproj
index ec8627e..e4e6e7e 100644
--- a/tests/DotPulsar.Tests/DotPulsar.Tests.csproj
+++ b/tests/DotPulsar.Tests/DotPulsar.Tests.csproj
@@ -1,4 +1,4 @@
-<Project Sdk="Microsoft.NET.Sdk">
+<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
@@ -36,7 +36,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers;
buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="ZstdNet" Version="1.4.5" />
- <PackageReference Include="ZstdSharp.Port" Version="0.7.4" />
+ <PackageReference Include="ZstdSharp.Port" Version="0.7.5" />
</ItemGroup>
<ItemGroup>