Skip to content

Commit f57214d

Browse files
committed
0.4: Ported zstd v1.5.0, performance improvements
1 parent b9b298d commit f57214d

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

76 files changed

+4026
-1480
lines changed

src/Zstd.Extern/ExternMethods.cs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ namespace Zstd.Extern
55
{
66
public class ExternMethods
77
{
8-
private const string DllName = "libzstd.dll";
8+
private const string DllName = "libzstd";
99

1010
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
1111
public static extern IntPtr ZSTD_createCCtx();
@@ -14,17 +14,31 @@ public class ExternMethods
1414
public static extern nuint ZSTD_freeCCtx(IntPtr cctx);
1515

1616
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
17-
public static extern nuint ZSTD_compressCCtx(IntPtr ctx, IntPtr dst, nuint dstCapacity, IntPtr src, nuint srcSize, int compressionLevel);
17+
public static extern nuint ZSTD_compressCCtx(IntPtr ctx, IntPtr dst, nuint dstCapacity, IntPtr src,
18+
nuint srcSize, int compressionLevel);
19+
20+
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
21+
public static extern nuint ZSTD_compress2(IntPtr ctx, IntPtr dst, nuint dstCapacity, IntPtr src, nuint srcSize);
1822

1923
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
2024
public static extern IntPtr ZSTD_createDCtx();
25+
2126
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
2227
public static extern nuint ZSTD_freeDCtx(IntPtr cctx);
2328

2429
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
25-
public static extern nuint ZSTD_decompressDCtx(IntPtr ctx, IntPtr dst, nuint dstCapacity, IntPtr src, nuint srcSize);
30+
public static extern nuint ZSTD_decompressDCtx(IntPtr ctx, IntPtr dst, nuint dstCapacity, IntPtr src,
31+
nuint srcSize);
2632

2733
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
2834
public static extern nuint ZSTD_compressBound(nuint srcSize);
35+
36+
[DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
37+
public static extern nuint ZSTD_CCtx_setParameter(IntPtr cctx, ZSTD_cParameter param, int value);
38+
39+
public enum ZSTD_cParameter
40+
{
41+
ZSTD_c_compressionLevel = 100,
42+
}
2943
}
3044
}

src/Zstd.Extern/libzstd.dll

53 KB
Binary file not shown.

src/ZstdSharp.Test/ZstdTest.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,12 @@ private Span<byte> CompressNative(byte[] srcBuffer, int compressBound, int level
2020
var cctx = ExternMethods.ZSTD_createCCtx();
2121
try
2222
{
23-
var length = ExternMethods.ZSTD_compressCCtx(cctx,
24-
(IntPtr) bufferPtr, (nuint) buffer.Length,
25-
(IntPtr) srcPtr, (nuint) srcBuffer.Length,
23+
ExternMethods.ZSTD_CCtx_setParameter(cctx, ExternMethods.ZSTD_cParameter.ZSTD_c_compressionLevel,
2624
level);
25+
26+
var length = ExternMethods.ZSTD_compress2(cctx,
27+
(IntPtr) bufferPtr, (nuint) buffer.Length,
28+
(IntPtr) srcPtr, (nuint) srcBuffer.Length);
2729
return new Span<byte>(buffer, 0, (int) length);
2830
}
2931
finally

src/ZstdSharp/BitOperations.cs renamed to src/ZstdSharp/Polyfills/BitOperations.cs

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4-
#if NETSTANDARD
4+
#if !NETCOREAPP3_0_OR_GREATER
55

66
using System.Runtime.CompilerServices;
77
using static ZstdSharp.UnsafeHelper;
@@ -16,17 +16,19 @@ namespace System.Numerics
1616
/// The methods use hardware intrinsics when available on the underlying platform,
1717
/// otherwise they use optimized software fallbacks.
1818
/// </summary>
19-
public unsafe static class BitOperations
19+
public static unsafe class BitOperations
2020
{
21-
private static readonly byte* TrailingZeroCountDeBruijn = GetArrayPointer(new byte[]
21+
// hack: should be public because of inline
22+
public static readonly byte* TrailingZeroCountDeBruijn = GetArrayPointer(new byte[]
2223
{
2324
00, 01, 28, 02, 29, 14, 24, 03,
2425
30, 22, 20, 15, 25, 17, 04, 08,
2526
31, 27, 13, 23, 21, 19, 16, 07,
2627
26, 12, 18, 06, 11, 05, 10, 09
2728
});
2829

29-
private static readonly byte* Log2DeBruijn = GetArrayPointer(new byte[]
30+
// hack: should be public because of inline
31+
public static readonly byte* Log2DeBruijn = GetArrayPointer(new byte[]
3032
{
3133
00, 09, 01, 10, 13, 21, 02, 29,
3234
11, 14, 16, 18, 22, 25, 03, 30,
@@ -40,7 +42,6 @@ public unsafe static class BitOperations
4042
/// </summary>
4143
/// <param name="value">The value.</param>
4244
[MethodImpl(MethodImplOptions.AggressiveInlining)]
43-
[InlineMethod.Inline]
4445
public static int Log2(uint value)
4546
{
4647
// The 0->0 contract is fulfilled by setting the LSB to 1.
@@ -77,7 +78,6 @@ public static int Log2(uint value)
7778
/// </summary>
7879
/// <param name="value">The value.</param>
7980
[MethodImpl(MethodImplOptions.AggressiveInlining)]
80-
[InlineMethod.Inline]
8181
public static int Log2(ulong value)
8282
{
8383
value |= 1;
@@ -98,7 +98,6 @@ public static int Log2(ulong value)
9898
/// </summary>
9999
/// <param name="value">The value.</param>
100100
[MethodImpl(MethodImplOptions.AggressiveInlining)]
101-
[InlineMethod.Inline]
102101
public static int TrailingZeroCount(int value)
103102
=> TrailingZeroCount((uint)value);
104103

@@ -108,7 +107,6 @@ public static int TrailingZeroCount(int value)
108107
/// </summary>
109108
/// <param name="value">The value.</param>
110109
[MethodImpl(MethodImplOptions.AggressiveInlining)]
111-
[InlineMethod.Inline]
112110
public static int TrailingZeroCount(uint value)
113111
{
114112
// Unguarded fallback contract is 0->0, BSF contract is 0->undefined
@@ -129,7 +127,6 @@ public static int TrailingZeroCount(uint value)
129127
/// </summary>
130128
/// <param name="value">The value.</param>
131129
[MethodImpl(MethodImplOptions.AggressiveInlining)]
132-
[InlineMethod.Inline]
133130
public static int TrailingZeroCount(long value)
134131
=> TrailingZeroCount((ulong)value);
135132

@@ -139,7 +136,6 @@ public static int TrailingZeroCount(long value)
139136
/// </summary>
140137
/// <param name="value">The value.</param>
141138
[MethodImpl(MethodImplOptions.AggressiveInlining)]
142-
[InlineMethod.Inline]
143139
public static int TrailingZeroCount(ulong value)
144140
{
145141
uint lo = (uint)value;
@@ -161,7 +157,6 @@ public static int TrailingZeroCount(ulong value)
161157
/// Any value outside the range [0..31] is treated as congruent mod 32.</param>
162158
/// <returns>The rotated value.</returns>
163159
[MethodImpl(MethodImplOptions.AggressiveInlining)]
164-
[InlineMethod.Inline]
165160
public static uint RotateLeft(uint value, int offset)
166161
=> (value << offset) | (value >> (32 - offset));
167162

@@ -174,7 +169,6 @@ public static uint RotateLeft(uint value, int offset)
174169
/// Any value outside the range [0..63] is treated as congruent mod 64.</param>
175170
/// <returns>The rotated value.</returns>
176171
[MethodImpl(MethodImplOptions.AggressiveInlining)]
177-
[InlineMethod.Inline]
178172
public static ulong RotateLeft(ulong value, int offset)
179173
=> (value << offset) | (value >> (64 - offset));
180174

@@ -187,7 +181,6 @@ public static ulong RotateLeft(ulong value, int offset)
187181
/// Any value outside the range [0..31] is treated as congruent mod 32.</param>
188182
/// <returns>The rotated value.</returns>
189183
[MethodImpl(MethodImplOptions.AggressiveInlining)]
190-
[InlineMethod.Inline]
191184
public static uint RotateRight(uint value, int offset)
192185
=> (value >> offset) | (value << (32 - offset));
193186

@@ -200,7 +193,6 @@ public static uint RotateRight(uint value, int offset)
200193
/// Any value outside the range [0..63] is treated as congruent mod 64.</param>
201194
/// <returns>The rotated value.</returns>
202195
[MethodImpl(MethodImplOptions.AggressiveInlining)]
203-
[InlineMethod.Inline]
204196
public static ulong RotateRight(ulong value, int offset)
205197
=> (value >> offset) | (value << (64 - offset));
206198
}

src/ZstdSharp/SkipLocalsInitAttribute.cs renamed to src/ZstdSharp/Polyfills/SkipLocalsInitAttribute.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// Licensed to the .NET Foundation under one or more agreements.
22
// The .NET Foundation licenses this file to you under the MIT license.
33

4-
#if !NET5_0
4+
#if !NET5_0_OR_GREATER
55
namespace System.Runtime.CompilerServices
66
{
77
/// <summary>
@@ -22,4 +22,4 @@ internal sealed class SkipLocalsInitAttribute : Attribute
2222
{
2323
}
2424
}
25-
#endif
25+
#endif

src/ZstdSharp/Polyfills/Unsafe.cs

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
#if !NETCOREAPP3_0_OR_GREATER
5+
6+
using InlineIL;
7+
using static InlineIL.IL.Emit;
8+
9+
namespace System.Runtime.CompilerServices
10+
{
11+
public static unsafe class Unsafe
12+
{
13+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
14+
public static T As<T>(object o)
15+
where T : struct
16+
{
17+
Ldarg(nameof(o));
18+
return IL.Return<T>();
19+
}
20+
21+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
22+
public static ref TTo As<TFrom, TTo>(ref TFrom source)
23+
{
24+
Ldarg(nameof(source));
25+
return ref IL.ReturnRef<TTo>();
26+
}
27+
28+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
29+
public static int SizeOf<T>()
30+
{
31+
Sizeof(typeof(T));
32+
return IL.Return<int>();
33+
}
34+
35+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
36+
public static ref T Add<T>(ref T source, int elementOffset)
37+
{
38+
Ldarg(nameof(source));
39+
Ldarg(nameof(elementOffset));
40+
Sizeof(typeof(T));
41+
Conv_I();
42+
Mul();
43+
IL.Emit.Add();
44+
return ref IL.ReturnRef<T>();
45+
}
46+
47+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
48+
public static void SkipInit<T>(out T value)
49+
{
50+
Ret();
51+
throw IL.Unreachable();
52+
}
53+
54+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
55+
public static ref T AsRef<T>(void* source)
56+
{
57+
// For .NET Core the roundtrip via a local is no longer needed
58+
#if NETCOREAPP
59+
IL.Push(source);
60+
return ref IL.ReturnRef<T>();
61+
#else
62+
// Roundtrip via a local to avoid type mismatch on return that the JIT inliner chokes on.
63+
IL.DeclareLocals(
64+
false,
65+
new LocalVar("local", typeof(int).MakeByRefType())
66+
);
67+
68+
IL.Push(source);
69+
Stloc("local");
70+
Ldloc("local");
71+
return ref IL.ReturnRef<T>();
72+
#endif
73+
}
74+
}
75+
}
76+
77+
#endif

src/ZstdSharp/Polyfills/Vector128.cs

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
#if !NETCOREAPP3_0_OR_GREATER
5+
6+
using System.Runtime.CompilerServices;
7+
8+
namespace System.Runtime.Intrinsics
9+
{
10+
public static class Vector128
11+
{
12+
internal const int Size = 16;
13+
14+
public static unsafe Vector128<byte> Create(byte value)
15+
{
16+
byte* pResult = stackalloc byte[16]
17+
{
18+
value,
19+
value,
20+
value,
21+
value,
22+
value,
23+
value,
24+
value,
25+
value,
26+
value,
27+
value,
28+
value,
29+
value,
30+
value,
31+
value,
32+
value,
33+
value,
34+
};
35+
36+
return Unsafe.AsRef<Vector128<byte>>(pResult);
37+
}
38+
39+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
40+
public static Vector128<U> As<T, U>(this Vector128<T> vector)
41+
where T : struct
42+
where U : struct =>
43+
Unsafe.As<Vector128<T>, Vector128<U>>(ref vector);
44+
45+
public static T GetElement<T>(this Vector128<T> vector, int index)
46+
where T : struct
47+
{
48+
ref T e0 = ref Unsafe.As<Vector128<T>, T>(ref vector);
49+
return Unsafe.Add(ref e0, index);
50+
}
51+
}
52+
}
53+
54+
#endif
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
#if !NETCOREAPP3_0_OR_GREATER
5+
6+
using System.Runtime.CompilerServices;
7+
using System.Runtime.InteropServices;
8+
9+
namespace System.Runtime.Intrinsics
10+
{
11+
[StructLayout(LayoutKind.Sequential, Size = Vector128.Size)]
12+
public readonly struct Vector128<T> : IEquatable<Vector128<T>>
13+
where T : struct
14+
{
15+
private readonly ulong _00;
16+
private readonly ulong _01;
17+
18+
public static int Count => Vector128.Size / Unsafe.SizeOf<T>();
19+
20+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
21+
public bool Equals(Vector128<T> other)
22+
{
23+
for (int i = 0; i < Count; i++)
24+
{
25+
if (!((IEquatable<T>)(this.GetElement(i))).Equals(other.GetElement(i)))
26+
{
27+
return false;
28+
}
29+
}
30+
31+
return true;
32+
}
33+
}
34+
}
35+
36+
#endif

0 commit comments

Comments
 (0)