1

「暗号化/復号化プロセス」が追加された場合のフットプリントを知るために、いくつかの測定値を取得しようとしています\. FileStreamまた、使用や返却などのさまざまなアプローチを比較してMemoryStreamいます (場合によっては必要です)。

大きなファイルがメモリに保持されているようです (Gen2 & LOH)。ヒープを完全にクリアするにはどうすればよいですか (FileStream アプローチで同じ Gen2 の結果を確認したい)?

usingというキーワードを使用しています。しかし、それでは希望がないようです!以下のコードを見るとわかるように、デフォルトのバッファ サイズも減らしました。しかし、私はまだGen2に数字を持っています

BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19041.572 (2004/?/20H1)
Intel Core i9-10920X CPU 3.50GHz, 1 CPU, 24 logical and 12 physical cores
  [Host]     : .NET Framework 4.8 (4.8.4250.0), X86 LegacyJIT
  DefaultJob : .NET Framework 4.8 (4.8.4250.0), X86 LegacyJIT

ファイル ストリームの結果

|              Method |      Mean |     Error |    StdDev |     Gen 0 |    Gen 1 | Gen 2 |   Allocated |
|-------------------- |----------:|----------:|----------:|----------:|---------:|------:|------------:|
| TXT300BYTES_Decrypt |  2.500 ms | 0.0444 ms | 0.0593 ms |   19.5313 |        - |     - |   105.11 KB |
|    PDF500KB_Decrypt | 12.909 ms | 0.2561 ms | 0.4348 ms |  187.5000 |  15.6250 |     - |  1019.59 KB |
|      PDF1MB_Decrypt | 14.125 ms | 0.2790 ms | 0.4001 ms |  406.2500 |  15.6250 |     - |  2149.96 KB |
|     TIFF1MB_Decrypt | 10.087 ms | 0.1949 ms | 0.1728 ms |  437.5000 |  31.2500 |     - |  2329.37 KB |
|     TIFF5MB_Decrypt | 22.779 ms | 0.4316 ms | 0.4239 ms | 2000.0000 | 187.5000 |     - | 10434.34 KB |
|    TIFF10MB_Decrypt | 38.467 ms | 0.7382 ms | 0.8205 ms | 3857.1429 | 285.7143 |     - | 20144.01 KB |

メモリ ストリームの結果

|              Method |      Mean |     Error |    StdDev |     Gen 0 |     Gen 1 |    Gen 2 |   Allocated |
|-------------------- |----------:|----------:|----------:|----------:|----------:|---------:|------------:|
| TXT300BYTES_Decrypt |  1.673 ms | 0.0098 ms | 0.0092 ms |   27.3438 |    1.9531 |        - |   147.69 KB |
|    PDF500KB_Decrypt |  9.956 ms | 0.1407 ms | 0.1248 ms |  328.1250 |  328.1250 | 328.1250 |  2316.08 KB |
|      PDF1MB_Decrypt | 11.998 ms | 0.0622 ms | 0.0486 ms |  921.8750 |  546.8750 | 531.2500 |   4737.8 KB |
|     TIFF1MB_Decrypt |  9.252 ms | 0.0973 ms | 0.0910 ms |  953.1250 |  671.8750 | 500.0000 |  4902.34 KB |
|     TIFF5MB_Decrypt | 24.220 ms | 0.1105 ms | 0.0980 ms | 2531.2500 |  718.7500 | 468.7500 | 20697.43 KB |
|    TIFF10MB_Decrypt | 41.463 ms | 0.5678 ms | 0.5033 ms | 4833.3333 | 1500.0000 | 916.6667 | 40696.31 KB |
public static class Constants
{
    public const int BufferSize = 40960; // Default is  81920
}

ファイル復号化方法

public class DescryptionService
{
    public async Task<string> DecryptFileAsync(string sourcePath)
    {
        var tempFilePath = SecurityFileHelper.CreateTempFile();
        using var sourceStream = new FileStream(sourcePath, FileMode.Open, FileAccess.Read, FileShare.Read);
        var keyBytes = Convert.FromBase64String(_key);
        using var destinationStream = new FileStream(tempFilePath, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);
        using var provider = new AesCryptoServiceProvider();

        var IV = new byte[provider.IV.Length];
        await sourceStream.ReadAsync(IV, 0, IV.Length);

        using var cryptoTransform = provider.CreateDecryptor(keyBytes, IV);
        using var cryptoStream = new CryptoStream(sourceStream, cryptoTransform, CryptoStreamMode.Read);
        await cryptoStream.CopyToAsync(destinationStream, Constants.BufferSize);

        return tempFilePath;
    }
}

メモリ復号化方法

public class DescryptionService
{
    public async Task<Stream> DecryptStreamAsync(Stream sourceStream)
    {
        var memoryStream = new MemoryStream();

        if (sourceStream.Position != 0) sourceStream.Position = 0;
        var tempFilePath = SecurityFileHelper.CreateTempFile();
        try
        {
            var keyBytes = Convert.FromBase64String(_key);
            using var destinationStream = new FileStream(tempFilePath, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite);
            using var provider = new AesCryptoServiceProvider();

            var IV = new byte[provider.IV.Length];
            await sourceStream.ReadAsync(IV, 0, IV.Length);

            using var cryptoTransform = provider.CreateDecryptor(keyBytes, IV);
            using var cryptoStream = new CryptoStream(sourceStream, cryptoTransform, CryptoStreamMode.Read);
            await cryptoStream.CopyToAsync(destinationStream, Constants.BufferSize);
            destinationStream.Position = 0;
            await destinationStream.CopyToAsync(memoryStream, Constants.BufferSize);
            await memoryStream.FlushAsync();
            memoryStream.Position = 0;
        }
        finally
        {
            if (File.Exists(tempFilePath))
                File.Delete(tempFilePath);
        }
        return memoryStream;
    }
}
// Calling it like this
using var encryptedStream = File.OpenRead("some file path");
var svc = new DecryptionService();
using var decryptedStream = await svc.DecryptStreamAsync(encryptedStream);

ちなみに、これらの行も追加しました:

decryptedStream.Position = 0;
decryptedStream.SetLength(0);
decryptedStream.Capacity = 0; // <<< this one will null bytes in memory stream

そして、まだこれらの結果を持っています

|              Method |      Mean |     Error |    StdDev |    Median |     Gen 0 |     Gen 1 |    Gen 2 |   Allocated |
|-------------------- |----------:|----------:|----------:|----------:|----------:|----------:|---------:|------------:|
| TXT300BYTES_Decrypt |  1.659 ms | 0.0322 ms | 0.0301 ms |  1.662 ms |   27.3438 |    1.9531 |        - |   148.03 KB |
|    PDF500KB_Decrypt | 11.085 ms | 0.2829 ms | 0.8297 ms | 10.769 ms |  328.1250 |  328.1250 | 328.1250 |  2312.33 KB |
|      PDF1MB_Decrypt | 12.479 ms | 0.2029 ms | 0.3859 ms | 12.402 ms |  906.2500 |  562.5000 | 531.2500 |  4734.61 KB |
|     TIFF1MB_Decrypt |  9.352 ms | 0.0971 ms | 0.0861 ms |  9.359 ms |  953.1250 |  593.7500 | 500.0000 |     4908 KB |
|     TIFF5MB_Decrypt | 24.760 ms | 0.4752 ms | 0.4213 ms | 24.607 ms | 2593.7500 |  843.7500 | 531.2500 | 20715.76 KB |
|    TIFF10MB_Decrypt | 41.976 ms | 0.6657 ms | 0.5901 ms | 42.011 ms | 4833.3333 | 1500.0000 | 916.6667 | 40744.43 KB |

私は何を取りこぼしたか?!:(

4

1 に答える 1

1

FileStream を使用したり、MemoryStream を返したりするなど、さまざまなアプローチを比較しています

大きなファイルがメモリに保持されているようです (Gen2 & LOH)。ヒープを完全にクリアするにはどうすればよいですか (FileStream アプローチで同じ Gen2 の結果を確認したい)?

ヒープをクリアすることの意味を理解しているかどうか、および の Gen 2 コレクションを表示する理由がわかりませんFileStream

使用しているハーネス (BenchmarkDotNet) は、ベンチマークの反復ごとに2 回のフル メモリ クリーンアップを強制します。これにより、すべてのベンチマークの反復が「クリーン ヒープ」で開始されることが保証されます。GC の自己調整の性質 (またはメモリ リークなどのその他のもの) が他のベンチマークに影響を与えないようにするために、すべてのベンチマークはスタンドアロン プロセスで実行されます。さらに、1k 操作 (ベンチマーク呼び出し) ごとにスケーリングされたコレクションの数。これにより、GC メトリックの完全な比較が可能になります。

2 つの異なるアプローチを比較していますが、おそらく (これはメモリ プロファイラーで検証する必要がある仮説です) そのうちの 1 つが大きなオブジェクトを割り当て、Gen 2コレクションを取得します。もう一方はそうではありません。これは、特定のソリューションのパフォーマンス特性であり、ビジネス ロジックを実装するときに考慮する必要があります。例: サービスのレイテンシーが低く、Gen 2 コレクションによる GC の長時間の一時停止が許容できない場合は、大きなオブジェクトを割り当てないアプローチを選択する必要があります。

Gen 2 コレクションを取り除きたい場合は、次を使用してメモリをプールしてみてください。

于 2020-10-20T13:04:30.723 に答える