19

ベンチマーク: http: //jsperf.com/substringing

それで、私は最初のHTML5ブラウザベースのクライアントサイドプロジェクトを立ち上げています。非常に大きなテキストファイルを、基本的に1つまたは複数のオブジェクトの配列に解析する必要があります。私はそれをどのようにコーディングするかを知っています。現在の私の主な関心事は、パーサーコードをできるだけ早く取得することであり、私の主なテストベッドはChromeです。ただし、サブストリングメソッドの違いを調べていると(私は長い間JavaScriptに触れていません)、このベンチマークはFireFoxと比較してChromeでは非常に遅いことに気付きました。なんで?

私の最初の仮定は、FireFoxのJSエンジンが文字列オブジェクトを処理する方法に関係していることです。FireFoxの場合、この操作は単純なポインター操作ですが、Chromeの場合は実際にハードコピーを実行します。しかし、Chromeポインター操作を行わない理由や、FireFox行う理由はわかりません。誰かが洞察を持っていますか?

JSPerfはFireFoxの結果を破棄しているようで、BrowserScopeに表示されていません。私の場合.substr()、FF4で9,568,203±1.44%Ops/secがオンになっています。

編集:つまり、実際にはChromeの下にFF3.5のパフォーマンス結果が表示されます。そこで、ポインター仮説をテストすることにしました。これにより、Substringsテストの2番目のリビジョン1,092,718±1.62%が作成されました。これは、FF4での1,195±3.81%Ops /秒とChromeでのOps/秒を実行し、わずか1000倍高速ですが、それでもパフォーマンスに不可解な違いがあります。

追記: いいえ、InternetExplorerを1回舐めることは心配していません。私は自分のスキルを向上させ、この言語をより深いレベルで理解しようとすることを心配しています。

4

2 に答える 2

16

Spidermonkey(FirefoxのJSエンジン)の場合、substring()呼び出しは新しい「依存文字列」を作成するだけです。これは、サブストリングがオフになっているものへのポインターと、開始オフセットと終了オフセットを格納する文字列オブジェクトです。これは正確にsubstring()高速化するためのものであり、不変の文字列が与えられた場合の明らかな最適化です。

V8がそれを行わない理由については...V8がスペースを節約しようとしている可能性があります。従属文字列の設定で、サブ文字列を保持しているが元の文字列を忘れた場合、元の文字列はGCされません。 substringは、文字列データの一部を使用しています。

いずれにせよ、私はV8ソースを見ただけで、依存する文字列をまったく実行していないように見えます。コメントは、なぜそうしないのかを説明していません。

[更新、2013年12月]:上記の回答を行ってから数か月後、Paul Draperが指摘しているように、V8は依存文字列のサポートを追加しました。

于 2011-06-01T01:43:45.130 に答える
1

.lengthベンチマーク結果からの読み取りを削除しましたか?

V8には文字列の表現がいくつかあると思います。

1. a sequence of ASCII bytes
2. a sequence of UTF-16 code units.
3. a slice of a string (result of substring)
4. a concatenation of two strings.

4番目は文字列を+=効率的にするものです。

推測しているだけですが、2つの文字列ポインタと1つの長さを小さなスペースに詰め込もうとすると、大きな長さをポインタでキャッシュできない可能性があるため、計算のために結合リンクリストをたどってしまう可能性があります長さ。Array.prototype.joinこれはもちろん、配列部分からフォーム(4)の文字列を作成することを前提としています。

それは、バッファコピーがなくても不一致を説明する検証可能な仮説につながります。

編集:

私はV8ソースコードを調べましたが、StringBuilderConcatは、特にプルを開始する場所ですruntime.cc

于 2011-06-01T01:43:16.427 に答える