C#を使用してMSHTML要素を単純に反復処理するのは非常に遅いことに直面しました。これは、 document.allコレクションを3回繰り返す小さな例です。空白のWPFアプリケーションとBrowserという名前のWebBrowserコントロールがあります。
public partial class MainWindow
{
public MainWindow()
{
InitializeComponent();
Browser.LoadCompleted += DocumentLoaded;
Browser.Navigate("http://google.com");
}
private IHTMLElementCollection _items;
private void DocumentLoaded(object sender, NavigationEventArgs e)
{
var dc = (HTMLDocument)Browser.Document;
_items = dc.all;
Test();
Test();
Test();
}
private void Test()
{
var sw = new Stopwatch();
sw.Start();
int i;
for (i = 0; i < _items.length; i++)
{
_items.item(i);
}
sw.Stop();
Debug.WriteLine("Items: {0}, Time: {1}", i, sw.Elapsed);
}
}
出力は次のとおりです。
Items: 274, Time: 00:00:01.0573245
Items: 274, Time: 00:00:00.0011637
Items: 274, Time: 00:00:00.0006619
1行と2行のパフォーマンスの違いはひどいものです。アンマネージC++とCOMを使用して同じコードを書き直そうとしましたが、パフォーマンスの問題はまったく発生しませんでした。アンマネージコードは1200倍高速に実行されます。残念ながら、実際のプロジェクトは単純な反復よりも複雑であるため、管理されていない状態にすることはできません。
ランタイムが、COMオブジェクトである参照されるHTML要素ごとにRCWを初めて作成することを理解しています。しかし、それはそんなに遅いのでしょうか?毎秒300アイテム、3,2 GHz CPUの100%コア負荷。
上記のコードのパフォーマンス分析: