From ae524f577afe457fde350df70529e1e8757f14a1 Mon Sep 17 00:00:00 2001 From: ahmed Date: Thu, 9 Apr 2026 16:36:05 +0300 Subject: [PATCH] Gvwie updated --- Libraries/Esiur/Data/Gvwie/GroupInt16Codec.cs | 119 +++---- Libraries/Esiur/Data/Gvwie/GroupInt32Codec.cs | 302 +++++++++++++++--- Libraries/Esiur/Data/Gvwie/GroupInt64Codec.cs | 254 ++++----------- .../Esiur/Data/Gvwie/GroupUInt16Codec.cs | 128 ++++---- .../Esiur/Data/Gvwie/GroupUInt32Codec.cs | 126 ++++---- .../Esiur/Data/Gvwie/GroupUInt64Codec.cs | 131 ++++---- .../Serialization/Gvwie/IntArrayGenerator.cs | 2 +- Tests/Serialization/Gvwie/IntArrayRunner.cs | 4 +- Tests/Serialization/Gvwie/Program.cs | 18 +- 9 files changed, 575 insertions(+), 509 deletions(-) diff --git a/Libraries/Esiur/Data/Gvwie/GroupInt16Codec.cs b/Libraries/Esiur/Data/Gvwie/GroupInt16Codec.cs index bfef751..820bb3f 100644 --- a/Libraries/Esiur/Data/Gvwie/GroupInt16Codec.cs +++ b/Libraries/Esiur/Data/Gvwie/GroupInt16Codec.cs @@ -6,17 +6,6 @@ namespace Esiur.Data.Gvwie; public static class GroupInt16Codec { - // Header layout: - // 1 | cccccc | w - // - // MSB = 1 => grouped form - // cccccc = 0..62 => short count = cccccc + 1 (1..63) - // cccccc = 63 => extended count, followed by varint(count - 64) - // w = 0 => width = 1 byte - // w = 1 => width = 2 bytes - // - // MSB = 0 => literal fast path for ZigZag values in 7 bits - // ----------------- Encoder ----------------- public static byte[] Encode(IList values) { @@ -36,7 +25,7 @@ public static class GroupInt16Codec } int start = i; - int width = WidthFromZigZag(zz); // 1 or 2 + int width = WidthFromZigZag(zz); // 1..2 int count = 1; // Build a run of same-width non-literal values @@ -55,10 +44,11 @@ public static class GroupInt16Codec count++; } - if (count <= 63) + if (count <= 60) { // Short group: // Header: 1 | (count-1)[6 bits] | (width-1)[1 bit] + // count field 000000..111011 => count 1..60 byte header = 0x80; header |= (byte)(((count - 1) & 0x3F) << 1); header |= (byte)((width - 1) & 0x01); @@ -67,13 +57,33 @@ public static class GroupInt16Codec else { // Extended group: - // Header: 1 | 111111 | (width-1)[1 bit] - // Followed by varint(count - 64) + // Header: 1 | g[6 bits] | (width-1)[1 bit] + // + // g = 111100 => LoL = 1 byte + // g = 111101 => LoL = 2 bytes + // g = 111110 => LoL = 3 bytes + // g = 111111 => LoL = 4 bytes + // + // LoL stores (count - 61) in little-endian form. + + uint extra = checked((uint)(count - 61)); + int lol = LengthOfLength(extra); + + byte groupBits = lol switch + { + 1 => 0b111100, + 2 => 0b111101, + 3 => 0b111110, + 4 => 0b111111, + _ => throw new InvalidOperationException("Invalid LoL.") + }; + byte header = 0x80; - header |= 0x7E; // count bits = 111111 + header |= (byte)(groupBits << 1); header |= (byte)((width - 1) & 0x01); dst.Add(header); - WriteVarUInt32(dst, (uint)(count - 64)); + + WriteLE(dst, extra, lol); } // Payload: 'count' zigzag values, LE, 'width' bytes each @@ -98,24 +108,33 @@ public static class GroupInt16Codec if ((h & 0x80) == 0) { - // Fast path: 7-bit ZigZag in low bits + // Fast path: 7-bit zigzag in low bits ushort zz7 = (ushort)(h & 0x7F); result.Add(UnZigZag16(zz7)); continue; } int countField = (h >> 1) & 0x3F; - int width = (h & 0x01) + 1; // 1 or 2 + int width = (h & 0x01) + 1; int count; - if (countField == 63) + + if (countField <= 59) { - uint extra = ReadVarUInt32(src, ref pos); - count = checked(64 + (int)extra); + // Short group: 0..59 => count 1..60 + count = countField + 1; } else { - count = countField + 1; + // Extended group: + // 60 => LoL=1 + // 61 => LoL=2 + // 62 => LoL=3 + // 63 => LoL=4 + int lol = countField - 59; + + uint extra = checked((uint)ReadLE(src, ref pos, lol)); + count = checked(61 + (int)extra); } for (int j = 0; j < count; j++) @@ -142,6 +161,15 @@ public static class GroupInt16Codec return z <= 0xFF ? 1 : 2; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static int LengthOfLength(uint value) + { + if (value <= 0xFFu) return 1; + if (value <= 0xFFFFu) return 2; + if (value <= 0xFFFFFFu) return 3; + return 4; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] private static void WriteLE(List dst, ushort value, int width) { @@ -149,50 +177,23 @@ public static class GroupInt16Codec dst.Add((byte)((value >> (8 * i)) & 0xFF)); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void WriteLE(List dst, uint value, int width) + { + for (int i = 0; i < width; i++) + dst.Add((byte)((value >> (8 * i)) & 0xFF)); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] private static uint ReadLE(ReadOnlySpan src, ref int pos, int width) { if ((uint)(pos + width) > (uint)src.Length) - throw new ArgumentException("Buffer underflow while reading group payload."); + throw new ArgumentException("Buffer underflow while reading payload."); uint v = 0; for (int i = 0; i < width; i++) v |= (uint)src[pos++] << (8 * i); + return v; } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static void WriteVarUInt32(List dst, uint value) - { - while (value >= 0x80) - { - dst.Add((byte)((value & 0x7F) | 0x80)); - value >>= 7; - } - - dst.Add((byte)value); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static uint ReadVarUInt32(ReadOnlySpan src, ref int pos) - { - uint result = 0; - int shift = 0; - - while (true) - { - if (pos >= src.Length) - throw new ArgumentException("Buffer underflow while reading varint."); - - byte b = src[pos++]; - result |= (uint)(b & 0x7F) << shift; - - if ((b & 0x80) == 0) - return result; - - shift += 7; - if (shift >= 35) - throw new ArgumentException("Varint is too long for UInt32."); - } - } } \ No newline at end of file diff --git a/Libraries/Esiur/Data/Gvwie/GroupInt32Codec.cs b/Libraries/Esiur/Data/Gvwie/GroupInt32Codec.cs index c25b08a..1c93d74 100644 --- a/Libraries/Esiur/Data/Gvwie/GroupInt32Codec.cs +++ b/Libraries/Esiur/Data/Gvwie/GroupInt32Codec.cs @@ -1,4 +1,200 @@ -using System; +//using System; +//using System.Collections.Generic; +//using System.Runtime.CompilerServices; + +//namespace Esiur.Data.Gvwie; + +//public static class GroupInt32Codec +//{ + +// // ----------------- Encoder ----------------- +// public static byte[] Encode(IList values, bool aligned = false) +// { +// var dst = new List(values.Count * 2); +// int i = 0; + +// while (i < values.Count) +// { +// uint zz = ZigZag32(values[i]); + +// // Fast path: single byte (MSB=0) when zigzag fits in 7 bits +// if (zz <= 0x7Fu) +// { +// dst.Add((byte)zz); +// i++; +// continue; +// } + +// int start = i; +// int width = WidthFromZigZag(zz, aligned); +// int count = 1; + +// // Build a run of same-width non-literal values +// while ((i + count) < values.Count) +// { +// uint z2 = ZigZag32(values[i + count]); + +// // Do not absorb literal-fast-path values into groups +// if (z2 <= 0x7Fu) +// break; + +// int w2 = WidthFromZigZag(z2, aligned); +// if (w2 != width) +// break; + +// count++; +// } + +// if (count <= 31) +// { +// // Short group: +// // Header: 1 | (count-1)[5 bits] | (width-1)[2 bits] +// byte header = 0x80; +// header |= (byte)(((count - 1) & 0x1F) << 2); +// header |= (byte)((width - 1) & 0x03); +// dst.Add(header); +// } +// else +// { +// // Extended group: +// // Header: 1 | 11111 | (width-1)[2 bits] +// // Followed by varint(count - 32) +// byte header = 0x80; +// header |= 0x7C; // count bits = 11111 +// header |= (byte)((width - 1) & 0x03); +// dst.Add(header); +// WriteVarUInt32(dst, (uint)(count - 32)); +// } + +// // Payload: 'count' zigzag values, LE, 'width' bytes each +// for (int k = 0; k < count; k++) +// WriteLE(dst, ZigZag32(values[start + k]), width); + +// i += count; +// } + +// return dst.ToArray(); +// } + +// // ----------------- Decoder ----------------- +// public static int[] Decode(ReadOnlySpan src) +// { +// var result = new List(); +// int pos = 0; + +// while (pos < src.Length) +// { +// byte h = src[pos++]; + +// if ((h & 0x80) == 0) +// { +// // Fast path: 7-bit ZigZag in low bits +// uint zz7 = (uint)(h & 0x7F); +// result.Add(UnZigZag32(zz7)); +// continue; +// } + +// int countField = (h >> 2) & 0x1F; +// int width = (h & 0x03) + 1; + +// int count; +// if (countField == 31) +// { +// // Extended group length +// uint extra = ReadVarUInt32(src, ref pos); +// count = checked(32 + (int)extra); +// } +// else +// { +// count = countField + 1; +// } + +// for (int j = 0; j < count; j++) +// { +// uint raw = (uint)ReadLE(src, ref pos, width); +// int val = UnZigZag32(raw); +// result.Add(val); +// } +// } + +// return result.ToArray(); +// } + +// // ----------------- Helpers ----------------- + +// [MethodImpl(MethodImplOptions.AggressiveInlining)] +// private static uint ZigZag32(int v) => (uint)((v << 1) ^ (v >> 31)); + +// [MethodImpl(MethodImplOptions.AggressiveInlining)] +// private static int UnZigZag32(uint u) => (int)((u >> 1) ^ (uint)-(int)(u & 1)); + +// [MethodImpl(MethodImplOptions.AggressiveInlining)] +// private static int WidthFromZigZag(uint z, bool aligned = false) +// { +// if (z <= 0xFFu) return 1; +// if (z <= 0xFFFFu) return 2; +// if (z <= 0xFFFFFFu) return aligned ? 4 : 3; +// return 4; +// } + +// [MethodImpl(MethodImplOptions.AggressiveInlining)] +// private static void WriteLE(List dst, uint value, int width) +// { +// for (int i = 0; i < width; i++) +// dst.Add((byte)((value >> (8 * i)) & 0xFF)); +// } + +// [MethodImpl(MethodImplOptions.AggressiveInlining)] +// private static ulong ReadLE(ReadOnlySpan src, ref int pos, int width) +// { +// if ((uint)(pos + width) > (uint)src.Length) +// throw new ArgumentException("Buffer underflow while reading group payload."); + +// ulong v = 0; +// for (int i = 0; i < width; i++) +// v |= (ulong)src[pos++] << (8 * i); +// return v; +// } + +// [MethodImpl(MethodImplOptions.AggressiveInlining)] +// private static void WriteVarUInt32(List dst, uint value) +// { +// while (value >= 0x80) +// { +// dst.Add((byte)((value & 0x7F) | 0x80)); +// value >>= 7; +// } + +// dst.Add((byte)value); +// } + +// [MethodImpl(MethodImplOptions.AggressiveInlining)] +// private static uint ReadVarUInt32(ReadOnlySpan src, ref int pos) +// { +// uint result = 0; +// int shift = 0; + +// while (true) +// { +// if (pos >= src.Length) +// throw new ArgumentException("Buffer underflow while reading varint."); + +// byte b = src[pos++]; +// result |= (uint)(b & 0x7F) << shift; + +// if ((b & 0x80) == 0) +// return result; + +// shift += 7; +// if (shift >= 35) +// throw new ArgumentException("Varint is too long for UInt32."); +// } +// } +//} + + + +using System; using System.Collections.Generic; using System.Runtime.CompilerServices; @@ -6,9 +202,8 @@ namespace Esiur.Data.Gvwie; public static class GroupInt32Codec { - // ----------------- Encoder ----------------- - public static byte[] Encode(IList values, bool use4for3 = false) + public static byte[] Encode(IList values, bool aligned = false) { var dst = new List(values.Count * 2); int i = 0; @@ -26,7 +221,7 @@ public static class GroupInt32Codec } int start = i; - int width = WidthFromZigZag(zz, use4for3); + int width = WidthFromZigZag(zz, aligned); int count = 1; // Build a run of same-width non-literal values @@ -38,17 +233,19 @@ public static class GroupInt32Codec if (z2 <= 0x7Fu) break; - int w2 = WidthFromZigZag(z2, use4for3); + int w2 = WidthFromZigZag(z2, aligned); if (w2 != width) break; count++; } - if (count <= 31) + if (count <= 28) { // Short group: // Header: 1 | (count-1)[5 bits] | (width-1)[2 bits] + // count field values: + // 00000..11011 => count = 1..28 byte header = 0x80; header |= (byte)(((count - 1) & 0x1F) << 2); header |= (byte)((width - 1) & 0x03); @@ -57,13 +254,33 @@ public static class GroupInt32Codec else { // Extended group: - // Header: 1 | 11111 | (width-1)[2 bits] - // Followed by varint(count - 32) + // Header: 1 | g[5 bits] | (width-1)[2 bits] + // + // g = 11100 => LoL = 1 byte + // g = 11101 => LoL = 2 bytes + // g = 11110 => LoL = 3 bytes + // g = 11111 => LoL = 4 bytes + // + // LoL stores (count - 29) in little-endian form. + + uint extra = checked((uint)(count - 29)); + int lol = LengthOfLength(extra); // 1..4 + + byte groupBits = lol switch + { + 1 => 0b11100, + 2 => 0b11101, + 3 => 0b11110, + 4 => 0b11111, + _ => throw new InvalidOperationException("Invalid LoL.") + }; + byte header = 0x80; - header |= 0x7C; // count bits = 11111 + header |= (byte)(groupBits << 2); header |= (byte)((width - 1) & 0x03); dst.Add(header); - WriteVarUInt32(dst, (uint)(count - 32)); + + WriteLE(dst, extra, lol); } // Payload: 'count' zigzag values, LE, 'width' bytes each @@ -98,15 +315,23 @@ public static class GroupInt32Codec int width = (h & 0x03) + 1; int count; - if (countField == 31) + + if (countField <= 27) { - // Extended group length - uint extra = ReadVarUInt32(src, ref pos); - count = checked(32 + (int)extra); + // Short group: 0..27 => count 1..28 + count = countField + 1; } else { - count = countField + 1; + // Extended group: + // 28 => LoL=1 + // 29 => LoL=2 + // 30 => LoL=3 + // 31 => LoL=4 + int lol = countField - 27; + + uint extra = checked((uint)ReadLE(src, ref pos, lol)); + count = checked(29 + (int)extra); } for (int j = 0; j < count; j++) @@ -137,6 +362,15 @@ public static class GroupInt32Codec return 4; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static int LengthOfLength(uint value) + { + if (value <= 0xFFu) return 1; + if (value <= 0xFFFFu) return 2; + if (value <= 0xFFFFFFu) return 3; + return 4; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] private static void WriteLE(List dst, uint value, int width) { @@ -148,46 +382,12 @@ public static class GroupInt32Codec private static ulong ReadLE(ReadOnlySpan src, ref int pos, int width) { if ((uint)(pos + width) > (uint)src.Length) - throw new ArgumentException("Buffer underflow while reading group payload."); + throw new ArgumentException("Buffer underflow while reading payload."); ulong v = 0; for (int i = 0; i < width; i++) v |= (ulong)src[pos++] << (8 * i); + return v; } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static void WriteVarUInt32(List dst, uint value) - { - while (value >= 0x80) - { - dst.Add((byte)((value & 0x7F) | 0x80)); - value >>= 7; - } - - dst.Add((byte)value); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static uint ReadVarUInt32(ReadOnlySpan src, ref int pos) - { - uint result = 0; - int shift = 0; - - while (true) - { - if (pos >= src.Length) - throw new ArgumentException("Buffer underflow while reading varint."); - - byte b = src[pos++]; - result |= (uint)(b & 0x7F) << shift; - - if ((b & 0x80) == 0) - return result; - - shift += 7; - if (shift >= 35) - throw new ArgumentException("Varint is too long for UInt32."); - } - } } \ No newline at end of file diff --git a/Libraries/Esiur/Data/Gvwie/GroupInt64Codec.cs b/Libraries/Esiur/Data/Gvwie/GroupInt64Codec.cs index 2a595bd..6ad4077 100644 --- a/Libraries/Esiur/Data/Gvwie/GroupInt64Codec.cs +++ b/Libraries/Esiur/Data/Gvwie/GroupInt64Codec.cs @@ -1,141 +1,4 @@ -//using System; -//using System.Collections.Generic; -//using System.Linq; -//using System.Text; -//using System.Threading.Tasks; -//using System; -//using System.Collections.Generic; -//using System.Runtime.CompilerServices; - -//namespace Esiur.Data.Gvwie; - -//public static class GroupInt64Codec -//{ -// // ----------------- Encoder ----------------- -// public static byte[] Encode(IList values) -// { -// var dst = new List(values.Count * 2); -// int i = 0; - -// while (i < values.Count) -// { -// ulong zz = ZigZag64(values[i]); - -// // Fast path: 1 byte when ZigZag fits in 7 bits -// if (zz <= 0x7Ful) -// { -// dst.Add((byte)zz); // MSB = 0 implicitly -// i++; -// continue; -// } - -// // Group path: up to 16 items sharing a common width (1..8 bytes) -// int start = i; -// int count = 1; -// int width = WidthFromZigZag(zz); - -// while (count < 16 && (i + count) < values.Count) -// { -// ulong z2 = ZigZag64(values[i + count]); -// int w2 = WidthFromZigZag(z2); -// width = Math.Max(width, w2); // widen as needed -// count++; -// } - -// // Header: 1 | (count-1)[4 bits] | (width-1)[3 bits] -// byte header = 0x80; -// header |= (byte)(((count - 1) & 0x0F) << 3); -// header |= (byte)((width - 1) & 0x07); -// dst.Add(header); - -// // Payload: 'count' ZigZag values, LE, 'width' bytes each -// for (int k = 0; k < count; k++) -// { -// ulong z = ZigZag64(values[start + k]); -// WriteLE(dst, z, width); -// } - -// i += count; -// } - -// return dst.ToArray(); -// } - -// // ----------------- Decoder ----------------- -// public static long[] Decode(ReadOnlySpan src) -// { -// var result = new List(); -// int pos = 0; - -// while (pos < src.Length) -// { -// byte h = src[pos++]; - -// if ((h & 0x80) == 0) -// { -// // Fast path: 7-bit ZigZag -// ulong zz7 = (ulong)(h & 0x7F); -// result.Add(UnZigZag64(zz7)); -// continue; -// } - -// int count = ((h >> 3) & 0x0F) + 1; // 1..16 -// int width = (h & 0x07) + 1; // 1..8 - -// for (int j = 0; j < count; j++) -// { -// ulong raw = ReadLE(src, ref pos, width); -// long val = UnZigZag64(raw); -// result.Add(val); -// } -// } - -// return result.ToArray(); -// } - -// // ----------------- Helpers ----------------- - -// [MethodImpl(MethodImplOptions.AggressiveInlining)] -// private static ulong ZigZag64(long v) => (ulong)((v << 1) ^ (v >> 63)); - -// [MethodImpl(MethodImplOptions.AggressiveInlining)] -// private static long UnZigZag64(ulong u) => (long)((u >> 1) ^ (ulong)-(long)(u & 1)); - -// [MethodImpl(MethodImplOptions.AggressiveInlining)] -// private static int WidthFromZigZag(ulong z) -// { -// if (z <= 0xFFUL) return 1; -// if (z <= 0xFFFFUL) return 2; -// if (z <= 0xFFFFFFUL) return 3; -// if (z <= 0xFFFFFFFFUL) return 4; -// if (z <= 0xFFFFFFFFFFUL) return 5; -// if (z <= 0xFFFFFFFFFFFFUL) return 6; -// if (z <= 0xFFFFFFFFFFFFFFUL) return 7; -// return 8; -// } - -// [MethodImpl(MethodImplOptions.AggressiveInlining)] -// private static void WriteLE(List dst, ulong value, int width) -// { -// for (int i = 0; i < width; i++) -// dst.Add((byte)((value >> (8 * i)) & 0xFF)); -// } - -// [MethodImpl(MethodImplOptions.AggressiveInlining)] -// private static ulong ReadLE(ReadOnlySpan src, ref int pos, int width) -// { -// if ((uint)(pos + width) > (uint)src.Length) -// throw new ArgumentException("Buffer underflow while reading group payload."); - -// ulong v = 0; -// for (int i = 0; i < width; i++) -// v |= (ulong)src[pos++] << (8 * i); -// return v; -// } -//} - - -using System; +using System; using System.Collections.Generic; using System.Runtime.CompilerServices; @@ -143,16 +6,6 @@ namespace Esiur.Data.Gvwie; public static class GroupInt64Codec { - // Header layout for grouped values: - // 1 | cccc | www - // - // MSB = 1 => grouped form - // cccc = 0..14 => short count = cccc + 1 (1..15) - // cccc = 15 => extended count, followed by varint(count - 16) - // www = 0..7 => width = www + 1 (1..8) - // - // MSB = 0 => literal fast path for ZigZag values in 7 bits - // ----------------- Encoder ----------------- public static byte[] Encode(IList values, bool aligned = false) { @@ -191,10 +44,11 @@ public static class GroupInt64Codec count++; } - if (count <= 15) + if (count <= 12) { // Short group: // Header: 1 | (count-1)[4 bits] | (width-1)[3 bits] + // count field 0000..1011 => count 1..12 byte header = 0x80; header |= (byte)(((count - 1) & 0x0F) << 3); header |= (byte)((width - 1) & 0x07); @@ -203,13 +57,33 @@ public static class GroupInt64Codec else { // Extended group: - // Header: 1 | 1111 | (width-1)[3 bits] - // Followed by varint(count - 16) + // Header: 1 | g[4 bits] | (width-1)[3 bits] + // + // g = 1100 => LoL = 1 byte + // g = 1101 => LoL = 2 bytes + // g = 1110 => LoL = 3 bytes + // g = 1111 => LoL = 4 bytes + // + // LoL stores (count - 13) in little-endian form. + + uint extra = checked((uint)(count - 13)); + int lol = LengthOfLength(extra); // 1..4 + + byte groupBits = lol switch + { + 1 => 0b1100, + 2 => 0b1101, + 3 => 0b1110, + 4 => 0b1111, + _ => throw new InvalidOperationException("Invalid LoL.") + }; + byte header = 0x80; - header |= 0x78; // count bits = 1111 + header |= (byte)(groupBits << 3); header |= (byte)((width - 1) & 0x07); dst.Add(header); - WriteVarUInt32(dst, checked((uint)(count - 16))); + + WriteLE(dst, extra, lol); } // Payload: 'count' zigzag values, LE, 'width' bytes each @@ -244,22 +118,29 @@ public static class GroupInt64Codec int width = (h & 0x07) + 1; int count; - if (countField == 15) + + if (countField <= 11) { - // Extended group length - uint extra = ReadVarUInt32(src, ref pos); - count = checked(16 + (int)extra); + // Short group: 0..11 => count 1..12 + count = countField + 1; } else { - count = countField + 1; + // Extended group: + // 12 => LoL=1 + // 13 => LoL=2 + // 14 => LoL=3 + // 15 => LoL=4 + int lol = countField - 11; + + uint extra = checked((uint)ReadLE(src, ref pos, lol)); + count = checked(13 + (int)extra); } for (int j = 0; j < count; j++) { ulong raw = ReadLE(src, ref pos, width); - long val = UnZigZag64(raw); - result.Add(val); + result.Add(UnZigZag64(raw)); } } @@ -285,7 +166,15 @@ public static class GroupInt64Codec if (z <= 0xFFFFFFFFFFFFul) return aligned ? 8 : 6; if (z <= 0xFFFFFFFFFFFFFFul) return aligned ? 8 : 7; return 8; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static int LengthOfLength(uint value) + { + if (value <= 0xFFu) return 1; + if (value <= 0xFFFFu) return 2; + if (value <= 0xFFFFFFu) return 3; + return 4; } [MethodImpl(MethodImplOptions.AggressiveInlining)] @@ -295,50 +184,23 @@ public static class GroupInt64Codec dst.Add((byte)((value >> (8 * i)) & 0xFF)); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void WriteLE(List dst, uint value, int width) + { + for (int i = 0; i < width; i++) + dst.Add((byte)((value >> (8 * i)) & 0xFF)); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] private static ulong ReadLE(ReadOnlySpan src, ref int pos, int width) { if ((uint)(pos + width) > (uint)src.Length) - throw new ArgumentException("Buffer underflow while reading group payload."); + throw new ArgumentException("Buffer underflow while reading payload."); ulong v = 0; for (int i = 0; i < width; i++) v |= (ulong)src[pos++] << (8 * i); + return v; } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static void WriteVarUInt32(List dst, uint value) - { - while (value >= 0x80) - { - dst.Add((byte)((value & 0x7F) | 0x80)); - value >>= 7; - } - - dst.Add((byte)value); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static uint ReadVarUInt32(ReadOnlySpan src, ref int pos) - { - uint result = 0; - int shift = 0; - - while (true) - { - if (pos >= src.Length) - throw new ArgumentException("Buffer underflow while reading varint."); - - byte b = src[pos++]; - result |= (uint)(b & 0x7F) << shift; - - if ((b & 0x80) == 0) - return result; - - shift += 7; - if (shift >= 35) - throw new ArgumentException("Varint is too long for UInt32."); - } - } } \ No newline at end of file diff --git a/Libraries/Esiur/Data/Gvwie/GroupUInt16Codec.cs b/Libraries/Esiur/Data/Gvwie/GroupUInt16Codec.cs index 25de2d1..e46da32 100644 --- a/Libraries/Esiur/Data/Gvwie/GroupUInt16Codec.cs +++ b/Libraries/Esiur/Data/Gvwie/GroupUInt16Codec.cs @@ -6,17 +6,6 @@ namespace Esiur.Data.Gvwie; public static class GroupUInt16Codec { - // Header layout: - // 1 | cccccc | w - // - // MSB = 1 => grouped form - // cccccc = 0..62 => short count = cccccc + 1 (1..63) - // cccccc = 63 => extended count, followed by varint(count - 64) - // w = 0 => width = 1 byte - // w = 1 => width = 2 bytes - // - // MSB = 0 => literal fast path for values in 7 bits - // ----------------- Encoder ----------------- public static byte[] Encode(IList values) { @@ -36,7 +25,7 @@ public static class GroupUInt16Codec } int start = i; - int width = WidthFromValue(v); // 1 or 2 + int width = WidthFromUInt16(v); // 1..2 int count = 1; // Build a run of same-width non-literal values @@ -48,17 +37,18 @@ public static class GroupUInt16Codec if (v2 <= 0x7F) break; - int w2 = WidthFromValue(v2); + int w2 = WidthFromUInt16(v2); if (w2 != width) break; count++; } - if (count <= 63) + if (count <= 60) { // Short group: // Header: 1 | (count-1)[6 bits] | (width-1)[1 bit] + // count field 000000..111011 => count 1..60 byte header = 0x80; header |= (byte)(((count - 1) & 0x3F) << 1); header |= (byte)((width - 1) & 0x01); @@ -67,13 +57,33 @@ public static class GroupUInt16Codec else { // Extended group: - // Header: 1 | 111111 | (width-1)[1 bit] - // Followed by varint(count - 64) + // Header: 1 | g[6 bits] | (width-1)[1 bit] + // + // g = 111100 => LoL = 1 byte + // g = 111101 => LoL = 2 bytes + // g = 111110 => LoL = 3 bytes + // g = 111111 => LoL = 4 bytes + // + // LoL stores (count - 61) in little-endian form. + + uint extra = checked((uint)(count - 61)); + int lol = LengthOfLength(extra); + + byte groupBits = lol switch + { + 1 => 0b111100, + 2 => 0b111101, + 3 => 0b111110, + 4 => 0b111111, + _ => throw new InvalidOperationException("Invalid LoL.") + }; + byte header = 0x80; - header |= 0x7E; // count bits = 111111 + header |= (byte)(groupBits << 1); header |= (byte)((width - 1) & 0x01); dst.Add(header); - WriteVarUInt32(dst, (uint)(count - 64)); + + WriteLE(dst, extra, lol); } // Payload: 'count' values, LE, 'width' bytes each @@ -98,30 +108,36 @@ public static class GroupUInt16Codec if ((h & 0x80) == 0) { - // Fast path: literal 7-bit unsigned value + // Fast path: 7-bit literal in low bits result.Add((ushort)(h & 0x7F)); continue; } int countField = (h >> 1) & 0x3F; - int width = (h & 0x01) + 1; // 1 or 2 + int width = (h & 0x01) + 1; int count; - if (countField == 63) + + if (countField <= 59) { - uint extra = ReadVarUInt32(src, ref pos); - count = checked(64 + (int)extra); + // Short group: 0..59 => count 1..60 + count = countField + 1; } else { - count = countField + 1; + // Extended group: + // 60 => LoL=1 + // 61 => LoL=2 + // 62 => LoL=3 + // 63 => LoL=4 + int lol = countField - 59; + + uint extra = ReadLE(src, ref pos, lol); + count = checked(61 + (int)extra); } for (int j = 0; j < count; j++) - { - ushort raw = (ushort)ReadLE(src, ref pos, width); - result.Add(raw); - } + result.Add((ushort)ReadLE(src, ref pos, width)); } return result.ToArray(); @@ -130,11 +146,20 @@ public static class GroupUInt16Codec // ----------------- Helpers ----------------- [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static int WidthFromValue(ushort v) + private static int WidthFromUInt16(ushort v) { return v <= 0xFF ? 1 : 2; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static int LengthOfLength(uint value) + { + if (value <= 0xFFu) return 1; + if (value <= 0xFFFFu) return 2; + if (value <= 0xFFFFFFu) return 3; + return 4; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] private static void WriteLE(List dst, ushort value, int width) { @@ -142,50 +167,23 @@ public static class GroupUInt16Codec dst.Add((byte)((value >> (8 * i)) & 0xFF)); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void WriteLE(List dst, uint value, int width) + { + for (int i = 0; i < width; i++) + dst.Add((byte)((value >> (8 * i)) & 0xFF)); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] private static uint ReadLE(ReadOnlySpan src, ref int pos, int width) { if ((uint)(pos + width) > (uint)src.Length) - throw new ArgumentException("Buffer underflow while reading group payload."); + throw new ArgumentException("Buffer underflow while reading payload."); uint v = 0; for (int i = 0; i < width; i++) v |= (uint)src[pos++] << (8 * i); + return v; } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static void WriteVarUInt32(List dst, uint value) - { - while (value >= 0x80) - { - dst.Add((byte)((value & 0x7F) | 0x80)); - value >>= 7; - } - - dst.Add((byte)value); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static uint ReadVarUInt32(ReadOnlySpan src, ref int pos) - { - uint result = 0; - int shift = 0; - - while (true) - { - if (pos >= src.Length) - throw new ArgumentException("Buffer underflow while reading varint."); - - byte b = src[pos++]; - result |= (uint)(b & 0x7F) << shift; - - if ((b & 0x80) == 0) - return result; - - shift += 7; - if (shift >= 35) - throw new ArgumentException("Varint is too long for UInt32."); - } - } } \ No newline at end of file diff --git a/Libraries/Esiur/Data/Gvwie/GroupUInt32Codec.cs b/Libraries/Esiur/Data/Gvwie/GroupUInt32Codec.cs index 292dd56..829ccc6 100644 --- a/Libraries/Esiur/Data/Gvwie/GroupUInt32Codec.cs +++ b/Libraries/Esiur/Data/Gvwie/GroupUInt32Codec.cs @@ -6,16 +6,6 @@ namespace Esiur.Data.Gvwie; public static class GroupUInt32Codec { - // Header layout: - // 1 | ccccc | ww - // - // MSB = 1 => grouped form - // ccccc = 0..30 => short count = ccccc + 1 (1..31) - // ccccc = 31 => extended count, followed by varint(count - 32) - // ww = 0..3 => width = ww + 1 (1..4) - // - // MSB = 0 => literal fast path for values in 7 bits - // ----------------- Encoder ----------------- public static byte[] Encode(IList values, bool aligned = false) { @@ -35,7 +25,7 @@ public static class GroupUInt32Codec } int start = i; - int width = WidthFromValue(v, aligned); + int width = WidthFromUInt32(v, aligned); int count = 1; // Build a run of same-width non-literal values @@ -47,17 +37,18 @@ public static class GroupUInt32Codec if (v2 <= 0x7Fu) break; - int w2 = WidthFromValue(v2, aligned); + int w2 = WidthFromUInt32(v2, aligned); if (w2 != width) break; count++; } - if (count <= 31) + if (count <= 28) { // Short group: // Header: 1 | (count-1)[5 bits] | (width-1)[2 bits] + // count field 00000..11011 => count 1..28 byte header = 0x80; header |= (byte)(((count - 1) & 0x1F) << 2); header |= (byte)((width - 1) & 0x03); @@ -66,13 +57,33 @@ public static class GroupUInt32Codec else { // Extended group: - // Header: 1 | 11111 | (width-1)[2 bits] - // Followed by varint(count - 32) + // Header: 1 | g[5 bits] | (width-1)[2 bits] + // + // g = 11100 => LoL = 1 byte + // g = 11101 => LoL = 2 bytes + // g = 11110 => LoL = 3 bytes + // g = 11111 => LoL = 4 bytes + // + // LoL stores (count - 29) in little-endian form. + + uint extra = checked((uint)(count - 29)); + int lol = LengthOfLength(extra); + + byte groupBits = lol switch + { + 1 => 0b11100, + 2 => 0b11101, + 3 => 0b11110, + 4 => 0b11111, + _ => throw new InvalidOperationException("Invalid LoL.") + }; + byte header = 0x80; - header |= 0x7C; // count bits = 11111 + header |= (byte)(groupBits << 2); header |= (byte)((width - 1) & 0x03); dst.Add(header); - WriteVarUInt32(dst, (uint)(count - 32)); + + WriteLE(dst, extra, lol); } // Payload: 'count' values, LE, 'width' bytes each @@ -97,30 +108,36 @@ public static class GroupUInt32Codec if ((h & 0x80) == 0) { - // Fast path: literal 7-bit unsigned value + // Fast path: 7-bit literal in low bits result.Add((uint)(h & 0x7F)); continue; } int countField = (h >> 2) & 0x1F; - int width = (h & 0x03) + 1; // 1..4 + int width = (h & 0x03) + 1; int count; - if (countField == 31) + + if (countField <= 27) { - uint extra = ReadVarUInt32(src, ref pos); - count = checked(32 + (int)extra); + // Short group: 0..27 => count 1..28 + count = countField + 1; } else { - count = countField + 1; + // Extended group: + // 28 => LoL=1 + // 29 => LoL=2 + // 30 => LoL=3 + // 31 => LoL=4 + int lol = countField - 27; + + uint extra = ReadLE(src, ref pos, lol); + count = checked(29 + (int)extra); } for (int j = 0; j < count; j++) - { - uint raw = (uint)ReadLE(src, ref pos, width); - result.Add(raw); - } + result.Add(ReadLE(src, ref pos, width)); } return result.ToArray(); @@ -129,7 +146,7 @@ public static class GroupUInt32Codec // ----------------- Helpers ----------------- [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static int WidthFromValue(uint v, bool aligned = false) + private static int WidthFromUInt32(uint v, bool aligned = false) { if (v <= 0xFFu) return 1; if (v <= 0xFFFFu) return 2; @@ -137,6 +154,15 @@ public static class GroupUInt32Codec return 4; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static int LengthOfLength(uint value) + { + if (value <= 0xFFu) return 1; + if (value <= 0xFFFFu) return 2; + if (value <= 0xFFFFFFu) return 3; + return 4; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] private static void WriteLE(List dst, uint value, int width) { @@ -145,49 +171,15 @@ public static class GroupUInt32Codec } [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static ulong ReadLE(ReadOnlySpan src, ref int pos, int width) + private static uint ReadLE(ReadOnlySpan src, ref int pos, int width) { if ((uint)(pos + width) > (uint)src.Length) - throw new ArgumentException("Buffer underflow while reading group payload."); + throw new ArgumentException("Buffer underflow while reading payload."); - ulong v = 0; + uint v = 0; for (int i = 0; i < width; i++) - v |= (ulong)src[pos++] << (8 * i); + v |= (uint)src[pos++] << (8 * i); + return v; } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static void WriteVarUInt32(List dst, uint value) - { - while (value >= 0x80) - { - dst.Add((byte)((value & 0x7F) | 0x80)); - value >>= 7; - } - - dst.Add((byte)value); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static uint ReadVarUInt32(ReadOnlySpan src, ref int pos) - { - uint result = 0; - int shift = 0; - - while (true) - { - if (pos >= src.Length) - throw new ArgumentException("Buffer underflow while reading varint."); - - byte b = src[pos++]; - result |= (uint)(b & 0x7F) << shift; - - if ((b & 0x80) == 0) - return result; - - shift += 7; - if (shift >= 35) - throw new ArgumentException("Varint is too long for UInt32."); - } - } } \ No newline at end of file diff --git a/Libraries/Esiur/Data/Gvwie/GroupUInt64Codec.cs b/Libraries/Esiur/Data/Gvwie/GroupUInt64Codec.cs index 9196965..176c521 100644 --- a/Libraries/Esiur/Data/Gvwie/GroupUInt64Codec.cs +++ b/Libraries/Esiur/Data/Gvwie/GroupUInt64Codec.cs @@ -6,16 +6,6 @@ namespace Esiur.Data.Gvwie; public static class GroupUInt64Codec { - // Header layout: - // 1 | cccc | www - // - // MSB = 1 => grouped form - // cccc = 0..14 => short count = cccc + 1 (1..15) - // cccc = 15 => extended count, followed by varint(count - 16) - // www = 0..7 => width = www + 1 (1..8) - // - // MSB = 0 => literal fast path for values in 7 bits - // ----------------- Encoder ----------------- public static byte[] Encode(IList values, bool aligned = false) { @@ -35,7 +25,7 @@ public static class GroupUInt64Codec } int start = i; - int width = WidthFromValue(v, aligned); + int width = WidthFromUInt64(v, aligned); int count = 1; // Build a run of same-width non-literal values @@ -47,17 +37,18 @@ public static class GroupUInt64Codec if (v2 <= 0x7Ful) break; - int w2 = WidthFromValue(v2, aligned); + int w2 = WidthFromUInt64(v2, aligned); if (w2 != width) break; count++; } - if (count <= 15) + if (count <= 12) { // Short group: // Header: 1 | (count-1)[4 bits] | (width-1)[3 bits] + // count field 0000..1011 => count 1..12 byte header = 0x80; header |= (byte)(((count - 1) & 0x0F) << 3); header |= (byte)((width - 1) & 0x07); @@ -66,13 +57,33 @@ public static class GroupUInt64Codec else { // Extended group: - // Header: 1 | 1111 | (width-1)[3 bits] - // Followed by varint(count - 16) + // Header: 1 | g[4 bits] | (width-1)[3 bits] + // + // g = 1100 => LoL = 1 byte + // g = 1101 => LoL = 2 bytes + // g = 1110 => LoL = 3 bytes + // g = 1111 => LoL = 4 bytes + // + // LoL stores (count - 13) in little-endian form. + + uint extra = checked((uint)(count - 13)); + int lol = LengthOfLength(extra); + + byte groupBits = lol switch + { + 1 => 0b1100, + 2 => 0b1101, + 3 => 0b1110, + 4 => 0b1111, + _ => throw new InvalidOperationException("Invalid LoL.") + }; + byte header = 0x80; - header |= 0x78; // count bits = 1111 + header |= (byte)(groupBits << 3); header |= (byte)((width - 1) & 0x07); dst.Add(header); - WriteVarUInt32(dst, checked((uint)(count - 16))); + + WriteLE(dst, extra, lol); } // Payload: 'count' values, LE, 'width' bytes each @@ -97,30 +108,36 @@ public static class GroupUInt64Codec if ((h & 0x80) == 0) { - // Fast path: literal 7-bit unsigned value + // Fast path: 7-bit literal in low bits result.Add((ulong)(h & 0x7F)); continue; } int countField = (h >> 3) & 0x0F; - int width = (h & 0x07) + 1; // 1..8 + int width = (h & 0x07) + 1; int count; - if (countField == 15) + + if (countField <= 11) { - uint extra = ReadVarUInt32(src, ref pos); - count = checked(16 + (int)extra); + // Short group: 0..11 => count 1..12 + count = countField + 1; } else { - count = countField + 1; + // Extended group: + // 12 => LoL=1 + // 13 => LoL=2 + // 14 => LoL=3 + // 15 => LoL=4 + int lol = countField - 11; + + uint extra = checked((uint)ReadLE(src, ref pos, lol)); + count = checked(13 + (int)extra); } for (int j = 0; j < count; j++) - { - ulong raw = ReadLE(src, ref pos, width); - result.Add(raw); - } + result.Add(ReadLE(src, ref pos, width)); } return result.ToArray(); @@ -129,18 +146,27 @@ public static class GroupUInt64Codec // ----------------- Helpers ----------------- [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static int WidthFromValue(ulong v, bool aligned = false) + private static int WidthFromUInt64(ulong v, bool aligned = false) { if (v <= 0xFFul) return 1; if (v <= 0xFFFFul) return 2; if (v <= 0xFFFFFFul) return aligned ? 4 : 3; if (v <= 0xFFFFFFFFul) return 4; - if (v <= 0xFFFFFFFFFFul) return aligned ? 8: 5; - if (v <= 0xFFFFFFFFFFFFul) return aligned ? 8: 6; + if (v <= 0xFFFFFFFFFFul) return aligned ? 8 : 5; + if (v <= 0xFFFFFFFFFFFFul) return aligned ? 8 : 6; if (v <= 0xFFFFFFFFFFFFFFul) return aligned ? 8 : 7; return 8; } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static int LengthOfLength(uint value) + { + if (value <= 0xFFu) return 1; + if (value <= 0xFFFFu) return 2; + if (value <= 0xFFFFFFu) return 3; + return 4; + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] private static void WriteLE(List dst, ulong value, int width) { @@ -148,50 +174,23 @@ public static class GroupUInt64Codec dst.Add((byte)((value >> (8 * i)) & 0xFF)); } + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static void WriteLE(List dst, uint value, int width) + { + for (int i = 0; i < width; i++) + dst.Add((byte)((value >> (8 * i)) & 0xFF)); + } + [MethodImpl(MethodImplOptions.AggressiveInlining)] private static ulong ReadLE(ReadOnlySpan src, ref int pos, int width) { if ((uint)(pos + width) > (uint)src.Length) - throw new ArgumentException("Buffer underflow while reading group payload."); + throw new ArgumentException("Buffer underflow while reading payload."); ulong v = 0; for (int i = 0; i < width; i++) v |= (ulong)src[pos++] << (8 * i); + return v; } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static void WriteVarUInt32(List dst, uint value) - { - while (value >= 0x80) - { - dst.Add((byte)((value & 0x7F) | 0x80)); - value >>= 7; - } - - dst.Add((byte)value); - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - private static uint ReadVarUInt32(ReadOnlySpan src, ref int pos) - { - uint result = 0; - int shift = 0; - - while (true) - { - if (pos >= src.Length) - throw new ArgumentException("Buffer underflow while reading varint."); - - byte b = src[pos++]; - result |= (uint)(b & 0x7F) << shift; - - if ((b & 0x80) == 0) - return result; - - shift += 7; - if (shift >= 35) - throw new ArgumentException("Varint is too long for UInt32."); - } - } } \ No newline at end of file diff --git a/Tests/Serialization/Gvwie/IntArrayGenerator.cs b/Tests/Serialization/Gvwie/IntArrayGenerator.cs index de04bca..fbe8e9d 100644 --- a/Tests/Serialization/Gvwie/IntArrayGenerator.cs +++ b/Tests/Serialization/Gvwie/IntArrayGenerator.cs @@ -24,7 +24,7 @@ public static class IntArrayGenerator /// - minGap / maxGap: approximate gap between runs (large gaps produce the jump examples) /// /// - public static void InitRng() => rng = new Random(24241564); + public static void InitRng(int seed= 24241564) => rng = new Random(seed); public static long[] GenerateRuns(int length, int minRunSize = 3, diff --git a/Tests/Serialization/Gvwie/IntArrayRunner.cs b/Tests/Serialization/Gvwie/IntArrayRunner.cs index 000330b..a9a0c80 100644 --- a/Tests/Serialization/Gvwie/IntArrayRunner.cs +++ b/Tests/Serialization/Gvwie/IntArrayRunner.cs @@ -32,7 +32,7 @@ namespace Esiur.Tests.Gvwie const int TEST_ITERATIONS = 100; const int SAMPLE_SIZE = 100; - Console.WriteLine(";Esiur;FlatBuffer;ProtoBuffer,MessagePack;BSON;CBOR;Avro,Optimal"); + Console.WriteLine(";Esiur;Aligned;FlatBuffer;ProtoBuffer,MessagePack;BSON;CBOR;Avro,Optimal"); @@ -177,7 +177,7 @@ namespace Esiur.Tests.Gvwie var file = $"run_chart_{gen.name}.csv"; System.IO.File.WriteAllText(file, sb.ToString()); var file2 = $"optimal_chart_{gen.name}.csv"; - System.IO.File.WriteAllText(file, sbr.ToString()); + System.IO.File.WriteAllText(file2, sbr.ToString()); Console.WriteLine($"Chart CSV written to: {file} {file2}"); } diff --git a/Tests/Serialization/Gvwie/Program.cs b/Tests/Serialization/Gvwie/Program.cs index 7f80951..0ee6687 100644 --- a/Tests/Serialization/Gvwie/Program.cs +++ b/Tests/Serialization/Gvwie/Program.cs @@ -5,13 +5,27 @@ using MessagePack; var e = GroupInt32Codec.Encode(new int[] {-12000, 15000, -1, 32760 }); +var test = IntArrayGenerator.GenerateInt32(5000, GeneratorPattern.Uniform); + +var aligned = GroupInt32Codec.Encode(test, true); +var nonAligned = GroupInt32Codec.Encode(test, false); + +var result1 = GroupInt32Codec.Decode(aligned); +var result2 = GroupInt32Codec.Decode(nonAligned); + +if (result1.SequenceEqual(result2)) + Console.WriteLine($"Passed {aligned.Length}"); + +if (result1.SequenceEqual(test)) + Console.WriteLine($"Passed {nonAligned.Length}"); + MessagePack.MessagePackSerializer.DefaultOptions = MessagePackSerializerOptions.Standard .WithCompression(MessagePackCompression.None); // optional; remove if you want raw size var ints = new IntArrayRunner(); -IntArrayGenerator.InitRng(); -ints.Run(); +//IntArrayGenerator.InitRng(); +//ints.Run(); IntArrayGenerator.InitRng(); ints.RunChart();