feat: Replaces Zlib with LibDeflate (#1774)
> [!Warning] > Users on Linux/OSX will need to follow the Readme > and make sure `libdeflate` is properly installed > [!Note] > **Developer Note** > The API for compression has changed. Use `Deflate.Standard` for the same functionality. ### Summary * Replaces Zlib with LibDeflate for a 50% performance improvement! * Adds MacOS 14 to properly test Arm64
This commit is contained in:
parent
35a292d2c7
commit
1f701e7b55
11 changed files with 279 additions and 282 deletions
23
Projects/Server/Compression/Deflate.cs
Normal file
23
Projects/Server/Compression/Deflate.cs
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
/*************************************************************************
|
||||
* ModernUO *
|
||||
* Copyright 2019-2024 - ModernUO Development Team *
|
||||
* Email: hi@modernuo.com *
|
||||
* File: Deflate.cs *
|
||||
* *
|
||||
* This program is free software: you can redistribute it and/or modify *
|
||||
* it under the terms of the GNU General Public License as published by *
|
||||
* the Free Software Foundation, either version 3 of the License, or *
|
||||
* (at your option) any later version. *
|
||||
* *
|
||||
* You should have received a copy of the GNU General Public License *
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
|
||||
*************************************************************************/
|
||||
|
||||
using System.IO.Compression;
|
||||
|
||||
namespace Server.Compression;
|
||||
|
||||
public static class Deflate
|
||||
{
|
||||
public static LibDeflateBinding Standard { get; } = new();
|
||||
}
|
||||
|
|
@ -19,6 +19,7 @@ using System.Collections.Generic;
|
|||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using Server.Buffers;
|
||||
using Server.Compression;
|
||||
|
||||
namespace Server;
|
||||
|
||||
|
|
@ -72,8 +73,8 @@ public static class MultiData
|
|||
}
|
||||
|
||||
var decompressedSize = entry.Size;
|
||||
if (Zlib.Unpack(compressionBuffer, ref decompressedSize, buffer, entry.CompressedSize) != ZlibError.Okay
|
||||
|| decompressedSize != entry.Size)
|
||||
if (Deflate.Standard.Unpack(compressionBuffer, buffer, out var bytesDecompressed) != LibDeflateResult.Success
|
||||
|| decompressedSize != bytesDecompressed)
|
||||
{
|
||||
throw new FileLoadException($"Error loading file {stream.Name}. Failed to unpack entry {i}.");
|
||||
}
|
||||
|
|
@ -118,11 +119,7 @@ public static class MultiData
|
|||
}
|
||||
|
||||
STArrayPool<byte>.Shared.Return(buffer);
|
||||
|
||||
if (compressionBuffer != null)
|
||||
{
|
||||
STArrayPool<byte>.Shared.Return(compressionBuffer);
|
||||
}
|
||||
STArrayPool<byte>.Shared.Return(compressionBuffer);
|
||||
}
|
||||
|
||||
private static void LoadMul(bool postHSMulFormat)
|
||||
|
|
|
|||
|
|
@ -16,10 +16,9 @@
|
|||
using System;
|
||||
using System.Buffers;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Server.Buffers;
|
||||
using Server.Collections;
|
||||
using Server.Compression;
|
||||
using Server.Gumps;
|
||||
using Server.Logging;
|
||||
|
||||
|
|
@ -49,7 +48,6 @@ public static class OutgoingGumpPackets
|
|||
|
||||
private static readonly byte[] _layoutBuffer = GC.AllocateUninitializedArray<byte>(0x20000);
|
||||
private static readonly byte[] _stringsBuffer = GC.AllocateUninitializedArray<byte>(0x20000);
|
||||
private static readonly byte[] _packBuffer = GC.AllocateUninitializedArray<byte>(0x20000);
|
||||
private static readonly OrderedSet<string> _stringsList = new();
|
||||
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
|
|
@ -63,36 +61,21 @@ public static class OutgoingGumpPackets
|
|||
return;
|
||||
}
|
||||
|
||||
var wantLength = Zlib.MaxPackSize(length);
|
||||
var packBuffer = _packBuffer;
|
||||
byte[] rentedBuffer = null;
|
||||
var dest = writer.RawBuffer[(writer.Position + 8)..];
|
||||
|
||||
if (wantLength > packBuffer.Length)
|
||||
var bytesPacked = Deflate.Standard.Pack(dest, span);
|
||||
if (bytesPacked == 0)
|
||||
{
|
||||
packBuffer = rentedBuffer = STArrayPool<byte>.Shared.Rent(wantLength);
|
||||
}
|
||||
|
||||
var packLength = wantLength;
|
||||
|
||||
var error = Zlib.Pack(packBuffer, ref packLength, span, length, ZlibQuality.Default);
|
||||
|
||||
if (error != ZlibError.Okay)
|
||||
{
|
||||
logger.Warning("Gump compression failed: {Error}", error);
|
||||
logger.Warning("Gump compression failed");
|
||||
|
||||
writer.Write(4);
|
||||
writer.Write(0);
|
||||
return;
|
||||
}
|
||||
|
||||
writer.Write(4 + packLength);
|
||||
writer.Write(4 + bytesPacked);
|
||||
writer.Write(length);
|
||||
writer.Write(packBuffer.AsSpan(0, packLength));
|
||||
|
||||
if (rentedBuffer != null)
|
||||
{
|
||||
STArrayPool<byte>.Shared.Return(rentedBuffer);
|
||||
}
|
||||
writer.Seek(bytesPacked, SeekOrigin.Current);
|
||||
}
|
||||
|
||||
public static void SendDisplayGump(this NetState ns, Gump gump, out int switches, out int entries)
|
||||
|
|
@ -141,11 +124,8 @@ public static class OutgoingGumpPackets
|
|||
stringsWriter.WriteBigUni(s);
|
||||
}
|
||||
|
||||
var worstLayoutLength = Zlib.MaxPackSize(layoutWriter.BytesWritten);
|
||||
var worstStringsLength = Zlib.MaxPackSize(stringsWriter.BytesWritten);
|
||||
var maxLength = 40 + worstLayoutLength + worstStringsLength;
|
||||
|
||||
var writer = new SpanWriter(maxLength);
|
||||
var writer = new SpanWriter(0x10000);
|
||||
writer.Write((byte)0xDD); // Packet ID
|
||||
writer.Seek(2, SeekOrigin.Current);
|
||||
|
||||
|
|
@ -171,6 +151,8 @@ public static class OutgoingGumpPackets
|
|||
{
|
||||
_stringsList.Clear();
|
||||
}
|
||||
|
||||
writer.Dispose();
|
||||
}
|
||||
|
||||
public static void SendDisplaySignGump(this NetState ns, Serial serial, int gumpId, string unknown, string caption)
|
||||
|
|
|
|||
|
|
@ -29,13 +29,15 @@
|
|||
<Delete Files="..\..\Distribution\Serilog.Sinks.Async.dll" ContinueOnError="true" />
|
||||
<Delete Files="..\..\Distribution\Serilog.Sinks.Console.dll" ContinueOnError="true" />
|
||||
<Delete Files="..\..\Distribution\wepoll.dll" ContinueOnError="true" />
|
||||
<Delete Files="..\..\Distribution\ZLib.Bindings.dll" ContinueOnError="true" />
|
||||
<Delete Files="..\..\Distribution\LibDeflate.Bindings.dll" ContinueOnError="true" />
|
||||
<Delete Files="..\..\Distribution\libdeflate.dll" ContinueOnError="true" />
|
||||
<Delete Files="..\..\Distribution\libdeflate.dylib" ContinueOnError="true" />
|
||||
</Target>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="CommunityToolkit.HighPerformance" Version="8.2.2" />
|
||||
<PackageReference Include="LibDeflate.Bindings" Version="1.0.0.120" />
|
||||
<PackageReference Include="PollGroup" Version="1.4.3" />
|
||||
<PackageReference Include="System.IO.Hashing" Version="8.0.0" />
|
||||
<PackageReference Include="Zlib.Bindings" Version="1.11.0" />
|
||||
|
||||
<PackageReference Include="ModernUO.Serialization.Annotations" Version="2.9.1" />
|
||||
<PackageReference Include="ModernUO.Serialization.Generator" Version="2.10.9" />
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue