なでしこ3はPythonより6.5倍速い!ベンチマークしてみました

なでしこの実行速度が話題になっていたので、久々に、手元にあるMacbook Pro(m1)でベンチマークしてみました。なでしこ3のPC版(Node.js版)と各種スクリプト言語を比較してみましょう。

# 再帰処理フィボナッチ勝負

まずはフィボナッチで試してみましょう。

## なでしこ3

なでしこ3.4.24で試してみました。

```nadesiko:fib.nako3
●FIB(Nの)
　　もし、N<2ならばNで戻る。
　　((N-1)のFIB)+((N-2)のFIB)で戻る。
ここまで。
(40のFIB)を表示。
```

実行してみると、下記のように4秒かかりました。
```
time cnako3 fib.nako3
102334155
cnako3 fib.nako3  3.94s user 0.05s system 98% cpu 4.078 total
```

## Python3

次に、Python 3.9.7で試してみます。速度には影響しないものの、タイプヒントも付けてみました。

```python:fib.py
def fib(n:int) -> int:
    if n < 2: return n
    return fib(n - 2) + fib(n - 1)
 
print(fib(40))
```

実行してみましょう。すると、なんと26.4秒かかってしまいました。Python遅いと言われていますが、やはりPython3.9だと再帰のコードが遅いですね。

```
time python3 fib.py
102334155
python3 fib.py  26.16s user 0.03s system 99% cpu 26.392 total
```

## Perl

次に、Perlで試してみましょう。

```perl:fib.pl
sub fib($) {
    return $_[0] if ($_[0] < 2);
    return fib($_[0] - 2) + fib($_[0] - 1);
}
 
print fib(40), "\n";
```

実行してみましょう。36.7秒かかり、Python3以上に遅いことが分かります。

```
time perl fib.pl
102334155
perl fib.pl  36.48s user 0.02s system 99% cpu 36.719 total
```

## Node.js

次に、なでしこ3のエンジンであるNode.jsで試してみましょう。

```js:fib.js
function fib(n) {
    if (n < 2) return n;
    return fib(n - 2) + fib(n - 1);
}
console.log(fib(40));
```

実行してみましょう。早い！やはり早いです！

```
time node fib.js
102334155
node fib.js  1.28s user 0.01s system 98% cpu 1.316 total
```

ここから、なでしこを使うと、コンパイル処理とか、内部で変数チェックとか、余分な処理が走るため、JSの3倍遅くなる事も分かります。

## PHP8

次に、PHP8.3.0で試してみましょう。PHP8になり、ずいぶん処理が速くなったと聞いていましたが、どうでしょうか。

```php:fib.php
<?php
function fib($n) {
    if ($n < 2) return $n;
    return fib($n - 2) + fib($n - 1);
}
 
echo fib(40)."\n";
```

実行してみましょう。9.695秒で、やはり、Node.jsには追いついていません。

```
time php fib.php
102334155
php fib.php  9.60s user 0.02s system 99% cpu 9.695 total
```

## Ruby

次に、日本発のプログラミング言語のRuby2.6.10p210で試してみましょう。Ruby3でなくてすみません。

```ruby:fib.rb
def fib(n)
    return n if (n < 2)
    return fib(n - 2) + fib(n - 1)
end
 puts fib(40)
```

実行してみましょう。13秒です！良い感じです。

```
time ruby fib.rb
102334155
ruby fib.rb  12.92s user 0.05s system 99% cpu 13.078 total
```

## 結果発表

結果をまとめてみました。今回の、スクリプト言語速度対決は、Node.jsが一番速く、実行エンジンとしてNode.jsを使っているなでしこ3がそれに次いで速いという結果になりました。とは言え、どの言語も素晴らしく、速度が遅い部類のPythonが2023年、最も使われています。もはや、PCは十分速くなり、素の実行速度など、それほど気にする必要は無いという時代になっていますね。

|順位| 言語 | 処理時間 |
|---| ---- | ----- |
|1| Node.js | 1.316
|2| なでしこ3 | 4.078
|3| PHP8 | 9.695
|4| Ruby2.6 | 13.078
|5| Python3 | 26.392
|6| Perl5 | 36.719

# (オマケ) 素数計算で対決

次に、オマケで、12345678以下の素数の個数を調べるプログラムで比較してみましょう。

```nadesiko:soe.nako3
●(最大値の)素数取得とは：
　　素数リスト＝[]
　　A=真を(最大値+1)だけ配列要素作成。
　　Iを2から最大値まで繰り返す：
　　　　もし、A[I]が真ならば：
　　　　　　素数リストにIを配列追加。
　　　　　　Jを（I*I）から最大値までIずつ増やし繰り返す：
　　　　　　　　A[J] = 偽
　　それは素数リスト
12345678の素数取得して要素数を表示。
```

実行してみましょう。0.785秒です。

```
time cnako3 soe.nako3
809227
cnako3 soe.nako3  0.73s user 0.08s system 103% cpu 0.785 total
```

次にPython3です。

```python:soe.py
def sieve_of_eratosthenes(limit):
    primes = []
    a = [True] * (limit + 1)
    for i in range(2, limit + 1):
        if a[i]:
            primes.append(i)
            for j in range(i*i, limit + 1, i):
                a[j] = False
    return primes

print(len(sieve_of_eratosthenes(12345678))) 
```

実行してみましょう。1.849秒でした。なでしこよりも2.4倍遅いという結果になりました。

```
time python3 soe.py
809227
python3 soe.py  1.73s user 0.04s system 96% cpu 1.849 total
```

続いて、PHPで試してみましょう。

```php:soe.php
<?php
function sieve_of_eratosthenes($limit) {
    $primes = array();
    $a = array_fill(0, $limit + 1, true);
    for ($i = 2; $i <= $limit; $i++) {
        if ($a[$i]) {
            array_push($primes, $i);
            for ($j = $i * $i; $j <= $limit; $j += $i) {
                $a[$j] = false;
            }
        }
    }
    return $primes;
}
$primes = sieve_of_eratosthenes(12345678);
echo count($primes)."\n";
```

PHPで試してみると、メモリエラーで実行できないようになっていました。コマンドラインで-d memory_limit=-1にすると、このエラーを回避できるとのこと、学びになりました。実行時間は、1.775秒でした。

```
time php -d memory_limit=-1 soe.php
809227
php -d memory_limit=-1 soe.php  1.69s user 0.05s system 98% cpu 1.775 total
```

## 素数計算勝負の結果

次のようになりました。今回は、3言語のみの比較ですが、やはり、Python3が遅いという結果です。

| 順位 | 言語 | 処理時間 |
| 1 | なでしこ3 | 0.785 |
| 2 | PHP8 | 1.775 |
| 3 | Python3 | 1.849 |

# まとめ

楽しいスクリプト言語ごとの速度結果勝負ですが、どうだったでしょうか。

スクリプト言語では、ChromeのJS実行エンジンを利用しているNode.jsがダントツで速く、虎の威を借る狐である「なでしこ3」は、それに次いで速いという結果になりました。Node.jsと比べると何倍も遅くなっていますが、PHPやPythonよりも速いので十分満足です。

もちろん、言語ごとに、最適化オプションがあるので、もっと速く実行することもできるでしょう。なでしこ3も、素のJavaScriptを出力するモードがあるので、これを利用すると、もっと速く実行できます。また、変数の引数チェックを省略するモードもあるので、それを使うともっと速くなります。

それでも、一番使い勝手の良いデフォルトモードで比較するのが公平なので、できるだけデフォルト状態で試してみました。

皆様の参考になれば幸いです。