public bool Compress(Stream inputUncompressed, Stream outputCompressed, int compressionBlockSize = DefaultBlockSize) { var workBlocksCount = (int)(inputUncompressed.Length / compressionBlockSize); workBlocksCount += (inputUncompressed.Length % compressionBlockSize > 0) ? 1 : 0; var compressionWorkThreads = new List <Thread>(); for (int i = 0; i < Environment.ProcessorCount; i += 1) { _buffers.Push(new byte[compressionBlockSize]); } using (var outputWriter = new BinaryWriter(outputCompressed)) { outputWriter.Write(ArchiveMagic); outputWriter.Write(compressionBlockSize); outputWriter.Write(workBlocksCount); _runningThreads = 0; var currentWorkBlock = 0; byte[] buf = null; while (currentWorkBlock <= workBlocksCount) { if (_runningThreads >= Environment.ProcessorCount) { MaxReasonableThreadsIdle(); continue; } lock (_threadLock) { buf = _buffers.Pop(); } var actualRead = inputUncompressed.Read(buf, 0, compressionBlockSize); var compressionWork = new Thread(ThreadCompressWork); compressionWorkThreads.Add(compressionWork); var compressionWorkData = new ThreadCompressWorkData(currentWorkBlock, buf, actualRead, outputWriter); _runningThreads += 1; compressionWork.Start(compressionWorkData); currentWorkBlock += 1; } AwaitRemainingRunningThreads(compressionWorkThreads); } _buffers.Clear(); return(true); }
private void GetCompressedBlockData(ThreadCompressWorkData workData, MemoryStream compressedBlockOutput) { using (MemoryStream compressedOutput = new MemoryStream()) { using (GZipStream compressionStream = new GZipStream(compressedOutput, CompressionLevel.Optimal, leaveOpen: true)) { compressionStream.Write(workData.DataForCompression, 0, workData.DataSize); } int compressedDataLength = (int)compressedOutput.Length; using (var binaryWriter = new BinaryWriter(compressedBlockOutput, System.Text.Encoding.Default, leaveOpen: true)) { binaryWriter.Write(workData.BlockIndex); binaryWriter.Write(compressedDataLength); compressedOutput.Seek(0, SeekOrigin.Begin); compressedOutput.CopyTo(binaryWriter.BaseStream); } } }