示例#1
0
        public void FrameRoundTrip(
            [ValueSource(typeof(Utilities), nameof(Utilities.CompressionLevels))]
            int compressionLevel,
            [Values(false, true)] bool useDictionary
            )
        {
#pragma warning disable 8632
            var dict = useDictionary
        ? Utilities.CreateDictionaryFromSamples(32 * 1024, 30, compressionLevel)
                       // ReSharper disable once RedundantCast // downlevel impl requires
        : (ZStdDictionaryBuilder?)null;
#pragma warning restore 8632

            var sample = Utilities.GenerateSampleBuffer(1000);

            Console.WriteLine($"Compression Level: {compressionLevel}");

            // compression

            using var cDict = dict?.CreateCompressorDictionary(compressionLevel);

            using var cCtx = new ZStdCompressor();

            cCtx.UseDictionary(cDict);

            var compressBufferSize = CCtx.GetUpperBound((UIntPtr)sample.Length).ToUInt32();

            var compressBuffer = new byte[compressBufferSize];

            cCtx.Set(CompressionParameter.CompressionLevel, compressionLevel);

            var compressedSize = cCtx.Compress(compressBuffer, sample);

            compressedSize.ToUInt64().Should().NotBe(0);

            var compressedFrame = new ArraySegment <byte>(compressBuffer, 0, (int)compressedSize);

            Console.WriteLine($"Compressed to: {compressedSize} ({(double) compressedSize / (double) sample.Length:P})");

            // decompression

            using var dDict = dict?.CreateDecompressorDictionary();

            using var dCtx = new ZStdDecompressor();

            dCtx.UseDictionary(dDict);

            var decompressBufferSize = DCtx.GetUpperBound(compressedFrame);

            decompressBufferSize.Should().NotBe(0);

            decompressBufferSize.Should().BeGreaterOrEqualTo((ulong)sample.Length);

            var decompressBuffer = new byte[decompressBufferSize];

            var decompressedSize = dCtx.Decompress(decompressBuffer, compressedFrame);

            (decompressedSize).Should().Be((UIntPtr)sample.Length);

            decompressBuffer.Take((int)decompressedSize).Should().Equal(sample);
        }
示例#2
0
        public void PiecemealStreamRoundTrip(
            [ValueSource(typeof(Utilities), nameof(Utilities.CompressionLevels))]
            int compressionLevel,
            [Values(0, 1, 2)] int flushMode,
            [Values(false, true)] bool useDictionary
            )
        {
#pragma warning disable 8632
            var dict = useDictionary
        ? Utilities.CreateDictionaryFromSamples(32 * 1024, 30, compressionLevel)
                       // ReSharper disable once RedundantCast // downlevel impl requires
        : (ZStdDictionaryBuilder?)null;
#pragma warning restore 8632

            var sample = Utilities.GenerateSampleBuffer(1000);

            Console.WriteLine($"Compression Level: {compressionLevel}");

            // lol "min" compression level
            var bufSize = (int)(CCtx.GetUpperBound((UIntPtr)sample.Length) * 1.05);
            var buffer  = new byte[bufSize]; // compression is much worse when fed piecemeal
            fixed(byte *pBuffer = &buffer[0])
            {
                using var compressed   = new MemoryRegionStream(pBuffer, bufSize);
                using var toDecompress = new MemoryRegionStream(pBuffer, bufSize);

                // compression

                var run          = 0;
                var wroteThisRun = 0L;

                IEnumerable <long> Feed()
                {
                    using (var cDict = dict?.CreateCompressorDictionary())
                        using (var compressStream = new ZStdCompressStream(compressed)) {
                            compressStream.Compressor.Set(CompressionParameter.CompressionLevel, compressionLevel);
                            compressStream.Compressor.UseDictionary(cDict);

                            for (var i = 0; i < sample.Length;)
                            {
                                // NOTE: failures happen if fed with below 12 bytes at a time
                                var x   = Utilities.Random.Next(1, 12) * (1 + run);
                                var rem = sample.Length - (i + x);
                                if (rem < 0)
                                {
                                    x += rem;
                                }
                                compressStream.Write(sample, i, x);
                                if (flushMode != 0)
                                {
                                    compressStream.Flush(flushMode == 2);
                                }
                                wroteThisRun = compressed.Length - toDecompress.Length;
                                if (wroteThisRun > 0)
                                {
                                    toDecompress.SetLength(compressed.Length);
                                }

                                i += x;
                                yield return(wroteThisRun);
                            }
                        }

                    wroteThisRun = compressed.Length - toDecompress.Length;
                    if (wroteThisRun > 0)
                    {
                        toDecompress.SetLength(compressed.Length);
                    }

                    Console.WriteLine($"Compressed to: {compressed.Length} ({(double) compressed.Length / (double) sample.Length:P})");

                    yield return(wroteThisRun);
                }

                // decompression

                compressed.Position = 0;

                using var dDict            = dict?.CreateDecompressorDictionary();
                using var decompressStream = new ZStdDecompressStream(toDecompress);

                decompressStream.Decompressor.UseDictionary(dDict);

                var decompressed = new byte[sample.Length];

                using var feed = Feed().GetEnumerator();
                var totalRead = 0;

                do
                {
                    int read;
                    var readThisRun = 0;
                    do
                    {
                        read = decompressStream.Read(decompressed, totalRead, decompressed.Length - totalRead);
                        decompressed.Skip(totalRead).Take(read).Should().Equal(sample.Skip(totalRead).Take(read));
                        totalRead   += read;
                        readThisRun += read;
                    } while (read > 0);

                    if (wroteThisRun != readThisRun)
                    {
                        Debugger.Break();
                    }
                    Console.WriteLine($"Run: {run++} Wrote: {wroteThisRun}, Read: {readThisRun}");
                } while (feed.MoveNext());

                decompressStream.ReadByte().Should().Be(-1);

                decompressed.Should().Equal(sample);
            }
        }
示例#3
0
        public void StreamRoundTrip(
            [ValueSource(typeof(Utilities), nameof(Utilities.CompressionLevels))]
            int compressionLevel,
            [Values(false, true)] bool useDictionary
            )
        {
#pragma warning disable 8632
            var dict = useDictionary
        ? Utilities.CreateDictionaryFromSamples(32 * 1024, 30, compressionLevel)
                       // ReSharper disable once RedundantCast // downlevel impl requires
        : (ZStdDictionaryBuilder?)null;
#pragma warning restore 8632

            var sample = Utilities.GenerateSampleBuffer(1000);

            Console.WriteLine($"Compression Level: {compressionLevel}");

            // compression

            using var cDict = dict?.CreateCompressorDictionary(compressionLevel);

            using var cCtx = new ZStdCompressor();

            cCtx.UseDictionary(cDict);

            var compressBufferSize = CCtx.GetUpperBound((UIntPtr)sample.Length).ToUInt32();

            var compressBuffer = new byte[compressBufferSize];

            UIntPtr compressedSize;

            cCtx.Set(CompressionParameter.CompressionLevel, compressionLevel);
            {
                var outBuf = new ArraySegment <byte>(compressBuffer, 0, compressBuffer.Length);
                var inBuf  = new ArraySegment <byte>(sample, 0, sample.Length);

                var amountRemaining = cCtx.StreamCompress(ref outBuf, ref inBuf, EndDirective.End);

                amountRemaining.ToUInt64().Should().Be(0);

                outBuf.Offset.Should().NotBe(0);
                inBuf.Offset.Should().NotBe(0);
                inBuf.Offset.Should().Be(sample.Length);

                compressedSize = (UIntPtr)outBuf.Offset;
            }

            var compressedFrame = new ArraySegment <byte>(compressBuffer, 0, (int)compressedSize);

            Console.WriteLine($"Compressed to: {compressedSize} ({(double) compressedSize / (double) sample.Length:P})");

            // decompression

            using var dDict = dict?.CreateDecompressorDictionary();

            using var dCtx = new ZStdDecompressor();

            dCtx.UseDictionary(dDict);

            var decompressBufferSize = DCtx.GetUpperBound(compressedFrame);

            var decompressBuffer = new byte[decompressBufferSize];
            {
                var outBuf = new ArraySegment <byte>(decompressBuffer, 0, decompressBuffer.Length);
                var inBuf  = compressedFrame;

                var amountRemaining = dCtx.StreamDecompress(ref outBuf, ref inBuf);

                amountRemaining.ToUInt64().Should().Be(0);
                outBuf.Count.Should().Be(0);
                inBuf.Count.Should().Be(0);
                outBuf.Offset.Should().NotBe(0);
                inBuf.Offset.Should().NotBe(0);
                outBuf.Offset.Should().Be(sample.Length);

                decompressBuffer.Take(outBuf.Offset).Should().Equal(sample);
            }
        }