2

たとえば、kernel32 を直接使用してファイルを削除した場合、この C# API の代わりとしてより効率的でしょうか?

System.IO.File.Delete(string Path);

このように dll をインポートし、DeleteFile("C:..") を使用すると、次のようになります。

[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool DeleteFile([MarshalAs(UnmanagedType.LPWStr)]string lpFileName);

コードの実行にかかる時間など、効率が向上しますか?

4

3 に答える 3

7

マネージコードが遅いというのはかなり一般的な誤解です。一般的にはそうではなく、Cコンパイラが生成するのと同じ種類のコードであるマシンコードを実行します。これは、オペレーティングシステム関数のラッパーである多数の種類の.Netフレームワーククラスには特に関係ありません。

Fileクラスのように。File.Delete()メソッドは、実際にはDeleteFile()winapi関数を呼び出します。必然的に、それはWindowsでファイルを削除する唯一の方法です。少なくともマネージドオペレーティングシステムが利用可能になるまでは、.NETFrameworkでできることは何もありません。実際にいつか起こるかもしれない、マイクロソフトの極秘のミドリプロジェクトはまさにそのようなオペレーティングシステムを開発することを目指しています。

しかし、それは未来の音楽です。現在、それはCコードの大きな塊であり、Fat32やNTFSなどのファイルシステムドライバーに埋め込まれていて、実際に仕事をこなします。ディスク速度で動作し、ファイルシステムドライバが削除が完了したことを確認するまでDeleteFile()は戻りません。これは非常に遅いです。昔ながらのハードドライブの場合は約50ミリ秒、SSDの場合はサブミリ秒の範囲です。

File.Delete()コードを追加し、多くのエラーチェックを実行します。渡す引数がnullでないことを確認する場合は、ファイルの削除権を拒否するサンドボックスでコードが実行されていないかどうかを確認し、ファイルパスで無効な文字をパスに指定していないかどうかを確認します。インクリメンタルパスをフルパスに変換し、それがまだ有効なパスであることを確認し、パス文字列が長すぎないかどうかを確認し、必要に応じて短いMS-Dos8.3名を長い名前に変換します。

これは大量の作業ですが、マイクロ秒単位で測定されます。DeleteFileをピンボークすると、そのコードはスキップされますが、せいぜい1%しか速くなりません。失われるのは信頼性です。これは、コードまたはデータにoopsが含まれている場合に、それについて通知されることを保証するものです。何が悪いのかを正確に伝える非常に明確な例外メッセージがあります。これらの数マイクロ秒に10億を掛けたものは、まだ機能しなかったDeleteFile()のデバッグに費やす時間と苦痛に匹敵するものではないため、非常に価値があります。

しないでください。

于 2013-01-13T22:45:25.147 に答える
2

確実に知る唯一の方法はそれをテストすることです。大量の一時ファイルを作成するコードを記述し、それらをすべて削除するのにかかる時間を計ります。

ここでのパフォーマンスの考慮事項:

  • ファイル削除にネイティブAPIを使用することでパフォーマンスが向上する可能性があります(kernel32)と
  • マーシャリングを使用する必要があることによるパフォーマンスの低下。

パフォーマンスの向上があったとしても、それが少しでも得られるのは私の予感です。

于 2013-01-13T21:51:28.383 に答える
2

削除操作の制限要因は、C# コードを OS コードに接続するコードではなく、ファイル システム操作を実行することです。これら 2 つの呼び出しに識別できる違いはありません。この API で kernel32 を直接呼び出すように切り替えるのは、間違いなく時期尚早の最適化です。

于 2013-01-13T21:53:39.143 に答える