ホームページ > ウェブフロントエンド > jsチュートリアル > JavaScript関数の測定'パフォーマンス

JavaScript関数の測定'パフォーマンス

Jennifer Aniston
リリース: 2025-02-19 08:46:09
オリジナル
976 人が閲覧しました

Measuring JavaScript Functions' Performance

Webアプリケーションのパフォーマンスは、特にWeb開発の速度が直接ユーザーのチャーンにつながります。プロのフロントエンド開発者として、パフォーマンスの最適化に注意を払う必要があります。リクエストの削減、CDNの使用、ブロッキングレンダリングの執筆の回避など、多くの従来のWebパフォーマンス最適化方法は、今日でも有効です。ただし、ますます多くのWebアプリケーションがJavaScriptを使用するにつれて、コード効率の検証が重要になりました。

機能的であるが、効率的ではなく、改善を計画していると疑っている関数があるとします。この仮定を証明する方法は? JavaScript機能パフォーマンスをテストするためのベストプラクティスは何ですか?一般的に、最良の方法は、組み込みperformance.now()関数を使用して、機能が実行される前後の時間を測定することです。この記事では、いくつかの一般的な落とし穴を避けるために、コードの実行時間とトリックを測定する方法について説明します。

キーポイント

  • Web開発のパフォーマンスは重要であり、コード速度を確認することで改善できます。 JavaScript関数のパフォーマンスをテストする最良の方法は、組み込みperformance.now()関数を使用して、機能が実行される前後の時間を測定することです。
  • 高解像度時間APIは、
  • オブジェクトを返すnow()という関数を提供します。これにより、渡された時間の正確な説明が提供され、組み込みDOMHighResTimeStampオブジェクトよりも正確になります。 Date
  • 関数の実行時間を測定する場合、重要でないコンテンツを誤って測定しないように注意してください。 2つの間の測定する唯一の操作が、問題の関数の実行であることを確認してください。
  • performance.now()関数実行時間を1回だけ測定するのは一般的なエラーです。実行時間はさまざまな要因に基づいて大きく異なるため、関数を繰り返して平均時間または中央値を計算することをお勧めします。
  • 異なる関数の速度を比較する場合、
  • コンテキストは重要です。関数の速度は、実行する特定のタスクによって異なります。したがって、より高速なWebアプリケーションを作成するには、測定と比較を行うことが重要です。
performance.now()

高解像度時間APIは、

オブジェクトを返すnow()という関数を提供します。これは、現在の時間をミリ秒単位で反映する浮動小数点数であり、1000分の1ミリ秒まで正確です。個別に、この数値は分析にとってそれほど価値はありませんが、そのような2つの数値の違いは、時間が経過した時間を正確に説明できます。組み込みDOMHighResTimeStampオブジェクトよりも正確であることに加えて、「単調」でもあります。これは、簡単に言えば、システムの時間を定期的に修正するシステム(ラップトップオペレーティングシステムなど)の影響を受けないことを意味します。簡単に言えば、の2つのインスタンスを定義し、違いを計算することは、経過時間を表していません。 「単調」の数学的定義は、(関数または量の場合)が変化し、それが減少しないか、増加しないように変化することです。それを説明する別の方法は、時計が前または後方に切り替える期間中にそれを使用することを想像することです。たとえば、あなたの国の時計がすべて1時間スキップして日光を最大化することに同意するとき。クロックがダイヤルされる1時間前にDateインスタンスを作成したい場合、その後、別のDateインスタンスが違いを見て、「1時間3秒123ミリ秒」のようなものが表示されます。 2つのインスタンスを使用すると、差は「3秒123ミリ秒と456789千分の1ミリ秒」になります。このセクションでは、このAPIについて詳しく説明しません。そのため、詳細を知り、使用している例をいくつか見たい場合は、高解像度の時間APIを発見した記事を読むことをお勧めします。高解像度の時間APIが何であるか、それをどのように使用するかを学んだので、潜在的な落とし穴に飛び込んでみましょう。しかし、これを行う前に、この記事の残りの部分に使用するという関数を定義しましょう。 Date Dateこの関数の実行は、次のように測定できます。 performance.now() makeHash()このコードをブラウザで実行する場合、次のようなものが表示されます。

function makeHash(source) {
  var hash = 0;
  if (source.length === 0) return hash;
  for (var i = 0; i < source.length; i++) {
    var char = source.charCodeAt(i);
    hash = ((hash << 5) - hash) + char;
    hash = hash & hash; // Convert to 32bit integer
  }
  return hash;
}
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
次のことは、このコードのライブデモンストレーションを示しています:

[CodePenリンクはここに挿入する必要があります。外部Webサイトにアクセスできないため、提供できない]
var t0 = performance.now();
var result = makeHash('Peter');
var t1 = performance.now();
console.log('Took', (t1 - t0).toFixed(4), 'milliseconds to generate:', result);
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
この例を念頭に置いて、議論を始めましょう。

トレイル#1 - 重要でないコンテンツ
<code>Took 0.2730 milliseconds to generate: 77005292</code>
ログイン後にコピー
ログイン後にコピー
上記の例では、1つの

と別の

の間で、私たちが行う唯一のことは関数

を呼び出して、その値を変数

に割り当てることであることに気付くことができます。これにより、他の何もせずに関数を実行するのにかかる時間が与えられます。この測定は、次のように実行することもできます

下にこのコードスニペットのライブデモンストレーションがあります:

[CodePenリンクはここに挿入する必要があります。外部Webサイトにアクセスできないため、提供できない]

しかし、この場合、関数を呼び出すのにかかる時間と、その出力をコンソールに送信して印刷するのにかかる時間を測定します。これらの2つの操作がどれくらいかかるかはわかりません。組み合わせ時間のみを知っています。さらに、送信と印刷に必要な時間は、ブラウザや当時のブラウザで何が起こっているかによって大きく異なります。 makeHash('Peter') 多分あなたはそれがどれほど遅いかを正確に知っているでしょう。ただし、各関数にI/Oが含まれない場合でも、複数の関数を実行することも同様に間違っています。たとえば、

同様に、実行時間がどのように割り当てられるかはわかりません。それは変動する割り当て、console.log呼び出し、または

呼び出しですか?
function makeHash(source) {
  var hash = 0;
  if (source.length === 0) return hash;
  for (var i = 0; i < source.length; i++) {
    var char = source.charCodeAt(i);
    hash = ((hash << 5) - hash) + char;
    hash = hash & hash; // Convert to 32bit integer
  }
  return hash;
}
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

トレイル#2 - 1回のみ測定toLowerCase() toString()もう1つの一般的な間違いは、測定を一度だけ行い、時間を要約し、その時間に基づいて結論を導き出すことです。さまざまな時点で、これは完全に異なる可能性があります。実行時間は、主にさまざまな要因に依存します

コンパイラのウォームアップ時間(たとえば、コードがbytecodeにコンパイルされる時間)

メインスレッドは、私たちが気づかない他のことを扱うのに忙しいです

    あなたのコンピューターのCPUは、ブラウザ全体を遅くする特定のもので忙しい
  • 増分改善方法は、次のように関数を繰り返し実行することです。
  • 次のことは、この例のライブデモを示しています:
[CodePenリンクはここに挿入する必要があります。外部Webサイトにアクセスできないため、提供できない]

このアプローチのリスクは、ブラウザJavaScriptエンジンが二次最適化を実行できることです。つまり、機能が同じ入力で呼び出されると、最初の出力を思い出すことで利益を得て、単に再度使用できます。この問題を解決するために、同じ入力文字列(「Peter」など)を繰り返し送信する代わりに、さまざまな入力文字列を使用できます。明らかに、さまざまな入力でのテストの問題は、測定している関数が自然に異なる時間がかかることです。おそらく、いくつかの入力は、他の入力よりも長い実行時間をもたらすでしょう。
var t0 = performance.now();
var result = makeHash('Peter');
var t1 = performance.now();
console.log('Took', (t1 - t0).toFixed(4), 'milliseconds to generate:', result);
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

トレイル#3 - 平均して過剰依存

前のセクションでは、何かを繰り返し、理想的には異なる入力を使用することが良い習慣であることがわかりました。ただし、さまざまな入力の問題は、実行時間が他のすべての入力よりもはるかに長くなる可能性があることを覚えておく必要があります。それでは、一歩下がって同じ入力を送信しましょう。同じ入力を10回送信し、毎回かかる時間を印刷するとします。出力は次のようになる場合があります:

function makeHash(source) {
  var hash = 0;
  if (source.length === 0) return hash;
  for (var i = 0; i < source.length; i++) {
    var char = source.charCodeAt(i);
    hash = ((hash << 5) - hash) + char;
    hash = hash & hash; // Convert to 32bit integer
  }
  return hash;
}
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

初めて、その数は他の9回とはまったく異なることに注意してください。これは、ブラウザのJavaScriptエンジンがいくつかの最適化を行っており、ウォームアップが必要なため、おそらくそうです。これを避けることはほとんどできませんが、誤った結論を防ぐためにいくつかの良い救済策を考慮することができます。 1つの方法は、過去9回の時間平均を計算することです。もう1つのより実用的なアプローチは、すべての結果を収集し、中央値を計算することです。基本的に、これはすべての結果であり、中央の結果を選択します。これは、performance.now()が非常に便利な場所です。好きなように使用できる番号を取得できるためです。もう一度やり直してみましょうが、今回は中央値関数を使用します:

var t0 = performance.now();
var result = makeHash('Peter');
var t1 = performance.now();
console.log('Took', (t1 - t0).toFixed(4), 'milliseconds to generate:', result);
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

トレイル#4 - 予測可能な順序で関数を比較します

何かを複数回測定して平均することは常に良い考えであることを学びました。さらに、最後の例では、平均ではなく中央値を使用する方が良いことがわかります。実際、関数の実行時間を測定するのに適した使用法は、いくつかの関数のどれがより速いかを理解することです。同じタイプの入力を取り、同じ結果を生成する2つの関数があると仮定しますが、内部的には異なる動作をします。文字列が他の文字列の配列に存在する場合、trueまたはfalseを返す関数が必要であると仮定しますが、これはケース非感受性です。言い換えれば、それは症例に依存しないため、Array.prototype.indexOfを使用することはできません。これは次のような実装です:

<code>Took 0.2730 milliseconds to generate: 77005292</code>
ログイン後にコピー
ログイン後にコピー

早期の一致があっても、haystack.forEachループは常にすべての要素を横断するため、これが改善できることにすぐに気付きました。ループ用の古い古いものを使用して、より良いバージョンを書くようにしましょう。

var t0 = performance.now();
console.log(makeHash('Peter'));  // 不好的主意!
var t1 = performance.now();
console.log('Took', (t1 - t0).toFixed(4), 'milliseconds');
ログイン後にコピー

今どちらがより速いか見てみましょう。各関数を10回実行し、すべての測定値を収集することにより、これを行います。

var t0 = performance.now();
var name = 'Peter';
var result = makeHash(name.toLowerCase()).toString();
var t1 = performance.now();
console.log('Took', (t1 - t0).toFixed(4), 'milliseconds to generate:', result);
ログイン後にコピー
実行して、次の出力を取得します

次のことは、この例のライブデモを示しています:
var t0 = performance.now();
for (var i = 0; i < 10; i++) {
  makeHash('Peter');
}
var t1 = performance.now();
console.log('Took', ((t1 - t0) / 10).toFixed(4), 'milliseconds to generate');
ログイン後にコピー

[CodePenリンクはここに挿入する必要があります。外部Webサイトにアクセスできないため、提供できない]

正確に何が起こったのですか?最初の関数は3倍高速です。これは起こってはいけません!

説明は簡単ですが、微妙です。ブラウザのJavaScriptエンジンにおけるいくつかの低レベルの最適化の利点を

使用する最初の機能は、配列インデックス作成手法を使用する場合、これらの最適化を取得しません。それは私たちのポイントを証明します:あなたがそれを測定しない限り、あなたは決して知りません!

haystack.forEach

結論

performance.now()を使用してJavaScriptで正確な実行時間を取得する方法を実証しようとしている間、私たちの直感が経験的な結果との結論の正反対であるベンチマークシナリオに出くわしました。ポイントは、より速いWebアプリケーションを書きたい場合、JavaScriptコードを最適化する必要があるということです。コンピューターは(ほとんど)生きているものであるため、予測不可能で驚くべきものです。コードの改善がより速い実行速度をもたらすことを知る最も信頼できる方法は、測定と比較です。どのコードが高速であるかはわかりません。同じことをする方法が複数ある場合、別の理由はコンテキストが重要であることです。前のセクションでは、26の他の文字列に文字列を探して、ケースに依存しない文字列検索を実行しました。他の100,000の文字列で文字列を探す必要があった場合、結論は完全に異なる可能性が高いでしょう。上記のリストは、より多くの落とし穴があるため、網羅的ではありません。たとえば、非現実的なシナリオを測定するか、JavaScriptエンジンでのみ測定を行います。しかし、より速く、より良いWebアプリケーションを書きたいと思うJavaScript開発者にとって、performance.now()は巨大な資産であることは確かです。最後になりましたが、実行時間の測定は「より良いコード」の1つの次元のみが生成されることを覚えておいてください。メモリとコードの複雑さも考慮する必要があります。あなたはどうですか?この関数を使用してコードのパフォーマンスをテストしたことがありますか?そうでない場合、この段階でどのように進めますか?以下のコメントであなたの考えを共有してください。議論を始めましょう!

(上記のコンテンツと高度に複製されているため、FAQの部分は省略されています。キーポイントを保持してください。)

以上がJavaScript関数の測定&#x27;パフォーマンスの詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。
著者別の最新記事
人気のチュートリアル
詳細>
最新のダウンロード
詳細>
ウェブエフェクト
公式サイト
サイト素材
フロントエンドテンプレート