LoginSignup
3
6

More than 5 years have passed since last update.

2017年度版 細かすぎて伝わらないJavaScriptの速度の話のコードを、コピペして動かしやすいように全文書いてみた話

Last updated at Posted at 2017-05-30

そういう話です

察してください。

2017年度版 細かすぎて伝わらないJavaScriptの速度の話 - Qiita

全部動かしました。

ベンチマーク関数を手に入れて嬉しかったので、ノリで

ベンチマーク関数の作り方を教えてもらったので、嬉しくてつい、ベンチマークしてみました。

JavaScript で全置換(正規表現も使った)の速度比較 - Qiita

JavaScript ベンチマーク関数などで実行する関数と引数を渡して動作させたい - スタック・オーバーフロー

結果

  • chrome windows (mac上のvwwareですけれども何か文句が....)

1394 msec ダブルクウォート
1201 msec シングルクウォート
218 msec if
185 msec switch
215 msec x++
229 msec x = (x + 1);
213 msec x = (x + 1)|0;
1050 msec + 連結
2564 msec concat 連結
1708 msec テンプレートリテラル
2351 msec += 連結
243 msec typeof x === "undefined"
206 msec x === undefined
265 msec x === void 0
193 msec if (!x) {}
217 msec if (x) {}
198 msec if (x === true) {}
213 msec if (!x) {}
241 msec if (x === false) {}
281 msec scope01++;
230 msec this.scope02++;
229 msec scope03++;
183 msec const test = 0;
2486 msec const test = new Test();
186 msec tryなし
146 msec Try/Catch
162 msec Try/Catch/Finally
load

  • node.js windows (mac上のvwwareですけれども文句ないよな。スタバでドヤ顔するためだけに使ってるんだから。windowsの方が使いやすいし。winmergeとかあるし)

983 msec ダブルクウォート
967 msec シングルクウォート
173 msec if
156 msec switch
203 msec x++
203 msec x = (x + 1);
172 msec x = (x + 1)|0;
876 msec + 連結
1888 msec concat 連結
1513 msec テンプレートリテラル
1841 msec += 連結
218 msec typeof x === "undefined"
204 msec x === undefined
203 msec x === void 0
171 msec if (!x) {}
172 msec if (x) {}
187 msec if (x === true) {}
187 msec if (!x) {}
172 msec if (x === false) {}
250 msec scope01++;
218 msec this.scope02++;
218 msec scope03++;
172 msec const test = 0;
546 msec const test = new Test();
171 msec tryなし
156 msec Try/Catch
172 msec Try/Catch/Finally
node.js

コード全文

index.html

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <title></title>
    <script src="script.js"></script>

<script>

var alert = function (message) {
    console.log(message);
};

window.addEventListener("load",function(eve){
    main('load');
},false);

</script>

  </head>
<body>

<form name="form01">
<table class="table02">
  <tr>
    <td>
      <input type="button" value="Test01" onclick="main('test01')" 
        style="width:150px;">

    </td>
  </tr>

  <tr>
    <td>
      <input type="button" value="Test02" onclick="main('test02')" 
        style="width:150px;">

    </td>
  </tr>

</table>
</form>


</body>
</html>
script.js
var alert = alert || function (message) {
    console.log(message);
};

var main = function (testName) {

  var benchMark = function (loopCount, func) {
    var startTime = new Date();

    var args = [].slice.call(arguments,2);

    for (var i = 0, max = loopCount - 1;
      i <= max - 1; i += 1) {
      func.apply(null, args);
    }

    var endTime = new Date();
    return endTime - startTime;
  }

  start = () => {
    const retryCount = 1000000;
    for (let i = 0; i < retryCount; i = i + 1) {
      const text = "abcde" + "fghij" + "klmno" + "pqrst" + "uvwxy" + "z" + i;
    }
  }
  console.log(benchMark(10, start) + ' msec ダブルクウォート');

  start = () => {
    const retryCount = 1000000;
    for (let i = 0; i < retryCount; i = i + 1) {
      const text = 'abcde' + 'fghij' + 'klmno' + 'pqrst' + 'uvwxy' + 'z' + i;
    }
  }
  console.log(benchMark(10, start) + ' msec シングルクウォート');

  start = () => {
    for (let i = 0; i < 10000000; i = i + 1) {
      const x = 1;
      // if
      if ( x === 1) {}
      else if ( x === 2) {}
      else if ( x === 3) {}
      else {}
    }
  }
  console.log(benchMark(10, start) + ' msec if');

  start = () => {
    for (let i = 0; i < 10000000; i = i + 1) {
      const x = 1;
      // switch
      switch (x) {
        case 1:
          break;
        case 2:
          break;
        case 3:
          break;
        default:
          break;
      }
    }
  }
  console.log(benchMark(10, start) + ' msec switch');

  start = () => {
    let x = 1;
    for (let i = 0; i < 10000000; i = i + 1) {
      x++;
    }
  }
  console.log(benchMark(10, start) + ' msec x++');

  start = () => {
    let x = 1;
    for (let i = 0; i < 10000000; i = i + 1) {
      x = (x + 1);
    }
  }
  console.log(benchMark(10, start) + ' msec x = (x + 1);');

  start = () => {
    let x = 1;
    for (let i = 0; i < 10000000; i = i + 1) {
      x = (x + 1)|0;
    }
  }
  console.log(benchMark(10, start) + ' msec x = (x + 1)|0;');

  start = () => {
    const a = "abcde";
    const f = "fghij";
    const k = "klmno";
    const p = "pqrst";
    const u = "uvwxyz";
    for (let i = 0; i < 1000000; i = i + 1) {
      let text = a + f + k + p + u + i;
    }
  }
  console.log(benchMark(10, start) + ' msec + 連結');

  start = () => {
    const a = "abcde";
    const f = "fghij";
    const k = "klmno";
    const p = "pqrst";
    const u = "uvwxyz";
    for (let i = 0; i < 1000000; i = i + 1) {
      let text = a.concat(f).concat(k).concat(p).concat(u).concat(i);
    }
  }
  console.log(benchMark(10, start) + ' msec concat 連結');

  start = () => {
    const a = "abcde";
    const f = "fghij";
    const k = "klmno";
    const p = "pqrst";
    const u = "uvwxyz";
    for (let i = 0; i < 1000000; i = i + 1) {
      let text = `${a}${f}${k}${p}${u}${i}`;
    }
  }
  console.log(benchMark(10, start) + ' msec テンプレートリテラル');

  start = () => {
    const a = "abcde";
    const f = "fghij";
    const k = "klmno";
    const p = "pqrst";
    const u = "uvwxyz";
    for (let i = 0; i < 1000000; i = i + 1) {
      let text = a;
      text += f;
      text += k;
      text += p;
      text += u;
      text += i;
    }
  }
  console.log(benchMark(10, start) + ' msec += 連結');

  start = () => {
    let x;
    for (let i = 0; i < 10000000; i = i + 1) {
      if (typeof x === 'undefined') {}
    }
  }
  console.log(benchMark(10, start) + ' msec typeof x === "undefined"');

  start = () => {
    let x;
    for (let i = 0; i < 10000000; i = i + 1) {
      if (x === undefined) {}
    }
  }
  console.log(benchMark(10, start) + ' msec x === undefined');

  start = () => {
    let x;
    for (let i = 0; i < 10000000; i = i + 1) {
      if (x === void 0) {}
      /* if (!x) {} */
    }
  }
  console.log(benchMark(10, start) + ' msec x === void 0');

  start = () => {
    let x;
    for (let i = 0; i < 10000000; i = i + 1) {
      if (!x) {}
    }
  }
  console.log(benchMark(10, start) + ' msec if (!x) {}');

  start = () => {
    const x = true;
    for(let i = 0; i < 10000000; i = i + 1) {
      if (x) {}
    }
  }
  console.log(benchMark(10, start) + ' msec if (x) {}');

  start = () => {
    const x = true;
    for(let i = 0; i < 10000000; i = i + 1) {
      if (x === true) {}
    }
  }
  console.log(benchMark(10, start) + ' msec if (x === true) {}');

  start = () => {
    const x = true;
    for(let i = 0; i < 10000000; i = i + 1) {
      if (!x) {}
      /* if (x === false) {} */
    }
  }
  console.log(benchMark(10, start) + ' msec if (!x) {}');

  start = () => {
    const x = true;
    for(let i = 0; i < 10000000; i = i + 1) {
      if (x === false) {}
    }
  }
  console.log(benchMark(10, start) + ' msec if (x === false) {}');

  scope01 = 1;
  class Test1 {
    constructor() {
      this.scope02 = 1;
    }
    start() {
      let scope03 = 1;
      for(let i = 0; i < 10000000; i = i + 1) {
         scope01++;
      }
    }
  }
  start = () => {
    const test = new Test1();
    test.start();
  }
  console.log(benchMark(10, start) + ' msec scope01++;');

  scope01 = 1;
  class Test2 {
    constructor() {
      this.scope02 = 1;
    }
    start() {
      let scope03 = 1;
      for(let i = 0; i < 10000000; i = i + 1) {
         this.scope02++;
      }
    }
  }
  start = () => {
    const test = new Test2();
    test.start();
  }
  console.log(benchMark(10, start) + ' msec this.scope02++;');

  scope01 = 1;
  class Test3 {
    constructor() {
      this.scope02 = 1;
    }
    start() {
      let scope03 = 1;
      for(let i = 0; i < 10000000; i = i + 1) {
         scope03++;
      }
    }
  }
  start = () => {
    const test = new Test3();
    test.start();
  }
  console.log(benchMark(10, start) + ' msec scope03++;');

  class Test {
    constructor() {}
  }
  start = () => {
    for(let i = 0; i < 10000000; i = i + 1) {
      const test = 0;
    }
  }
  console.log(benchMark(10, start) + ' msec const test = 0;');

  start = () => {
    for(let i = 0; i < 10000000; i = i + 1) {
      const test = new Test();
    }
  }
  console.log(benchMark(10, start) + ' msec const test = new Test();');

  start = () => {
    for(let i = 0; i < 10000000; i = i + 1) {
      const x = 0;
    }
  }
  console.log(benchMark(10, start) + ' msec tryなし');

  start = () => {
    for(let i = 0; i < 10000000; i = i + 1) {
      try {
        const x = 0;
      }
      catch (exception) {}
    }
  }
  console.log(benchMark(10, start) + ' msec Try/Catch');

  start = () => {
    for(let i = 0; i < 10000000; i = i + 1) {
      try {
        const x = 0;
      }
      catch (exception) {}
      finally {}
    }
  }
  console.log(benchMark(10, start) + ' msec Try/Catch/Finally');

  alert(testName);
}

if (typeof module !== 'undefined') {
  module.exports = main;
}

call_script_node.js

var main = require('./script.js');
main('node.js');

run_node_script.bat
node call_script_node.js
pause

感想

ちょっとコピペが大変でした。ベンチマーク関数の呼び出しのオーバーヘッド的な不正確さがあるかもしれませんが、そこはみなかったことにしてください。

ご自身の環境でいろんなブラウザで試したりしてもいいんじゃないでしょうか。

全体的に差がほとんどなくて、誤差に近いきがしなくも、ないところもありますが、文字列の結合などはすごく差がありますね。

元ネタを提供していただいて、インスピレーションくださった、@gctoyoさん、大変ありがとうございます。

3
6
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
6