【Bun】先日試したベンチのどの行が速いのか確かめて、最後に少し驚いた。

先日試したこのベンチのどの行が速いのかちょっと確かめてみたくなった。

https://qiita.com/toshirot/items/c4d090bc38f9b85d8cdd

このコードは「郵便局の郵便番号データ 18M のcsv(124,332行) を for で回しながら行数カウントするだけのスクリプト」です。やってることはそれほど多くないので、上から順番にベンチを試してみたいと思います。

ただ、今回は Bun と Node.js を完全に区別するべく、node_modules の無いBun用と node_modules　の有る Node.js 用のふたつのディレクトリを作って試してみようと思います。

# 今回の環境

クラウド： Azure VM (これはオンプレでも何でも良い)
OS：　Ubuntu 20.04.6 LTS (GNU/Linux 5.15.0-1050-azure x86_64)
Bun：　1.0.15 ( https://bun.sh/blog )
Node.js： v20.9.0

# 準備
#### 共通の作業

```sh:bun用ディレクトリを作って入り read.js を作成する
$ mkdir read-zip-csv_bun
$ cd read-zip-csv_bun

# 郵便番号データをコピーする
$ cp ＜ファイルへのパス＞/zip.csv ./

# 下記の共通read.jsを書く
$ vi read.js

```
```sh:Node.js用ディレクトリを作って入り read.js を作成する
$ mkdir read-zip-csv_node
$ cd read-zip-csv_node

# 郵便番号データをコピーする
$ cp ＜ファイルへのパス＞/zip.csv ./

# 下記の共通read.jsを書く
$ vi read.js
```
```js:共通のread.js
console.time('csv read'); // 計測開始
const fs = require('fs');

let path='./zip.csv';

const csv =  fs.readFileSync(path, 'utf8');
const oj=csv.split('\n')
let count=0;

for(let i=0; i<oj.length;i++){
    let line=oj[i].split(',')
    count++;
}
console.log(count);
console.timeEnd('csv read'); // 計測終了
```

生成されたツリー

```
./read-zip-csv_bun/
    ├─read.js
    └─zip.csv

./read-zip-csv_node/
    ├─read.js
    └─zip.csv
```

#### bun用ディレクトリでの作業

at ./read-zip-csv_bun

```sh:bun用ディレクトリで read.js を実行する
$ bun read.js
124332
[124.22ms] csv read
```

#### noden用ディレクトリでの作業
at ./read-zip-csv_node

```sh:bun用ディレクトリで read.js を実行する
$ node read.js
124332
csv read: 290.21ms
```

# ここから順にやっていきます

```js:a-1.js requireだけ
console.time('csv read'); // 計測開始
const fs = require('fs');
console.timeEnd('csv read'); // 計測終了
```

```sh:結果
bun a-1.js
[12.05ms] csv read

$ node a-1.js
csv read: 3.343ms
```
a-1.js
<b> require('fs')</b>
bun: 12.05ms
node: 3.343ms ◎の勝ち
```js:a-2.js readFileSyncまで
console.time('csv read'); // 計測開始
const fs = require('fs');
let path='./zip.csv';
const csv =  fs.readFileSync(path, 'utf8');
console.timeEnd('csv read'); // 計測終了
```

```sh:結果 
$ bun a-2.js
[41.19ms] csv read

$ node a-2.js
csv read: 137.513ms
```
a-1.jsとa-2.jsの差分
<b> fs.readFileSync</b>
bun: 29.14ms ◎bunの勝ち
node: 134.17ms

```js:a-3.js splitまで
console.time('csv read'); // 計測開始
const fs = require('fs');
let path='./zip.csv';
const csv =  fs.readFileSync(path, 'utf8');
const oj=csv.split('\n')
console.timeEnd('csv read'); // 計測終了
```
```sh:結果
$ bun a-3.js
[51.03ms] csv read

$ node a-3.js
csv read: 165.209ms
```

a-2.jsとa-3.jsの差分
<b> .split</b>
bun: 9.84ms ◎bunの勝ち
node: 27.696ms

```js:a-4.js forまで
console.time('csv read'); // 計測開始
const fs = require('fs');
let path='./zip.csv';
const csv =  fs.readFileSync(path, 'utf8');
const oj=csv.split('\n')
let count=0;
for(let i=0; i<oj.length;i++){
    let line=oj[i].split(',')
    count++;
}
console.timeEnd('csv read'); // 計測終了
```
```sh:結果
$ bun a-4.js
[122.76ms] csv read

$ node a-4.js
csv read: 285.202ms
```

a-3.jsとa-4.jsの差分
<b> for</b>
bun: 71.73ms ◎bunの勝ち
node: 119.993ms

```js:a-5.js console.log(count)まで
console.time('csv read'); // 計測開始
const fs = require('fs');
let path='./zip.csv';
const csv =  fs.readFileSync(path, 'utf8');
const oj=csv.split('\n')
let count=0;
for(let i=0; i<oj.length;i++){
    let line=oj[i].split(',')
    count++;
}
console.log(count);
console.timeEnd('csv read'); // 計測終了
```
```sh:結果
$ bun a-5.js
124332
[123.30ms] csv read

$ node a-5.js
124332
csv read: 289.192ms
```
a-4.jsとa-5.jsの差分
<b> console.log</b>
bun: 0.54ms ◎bunの勝ち
node: 3.99ms

# まとめ
require('fs')の読み込み以外は Bun の勝ちだった。全体通してはa-5.jsでみたとおりほぼ 2.3倍の差がついた。

require('fs')は、Node.jsもビルトインモジュールなので速いのだろうか。これを importにしたらどうなるのかと思い、これだけ試してみた。

```js:b-1.js Bun用 
console.time('csv read'); // 計測開始
import fs from 'fs'; //import分に変えてみる
console.timeEnd('csv read'); // 計測終了
```
```js:b-1.mjs Node.js用
console.time('csv read'); // 計測開始
import fs from 'fs'; //import分に変えてみる
console.timeEnd('csv read'); // 計測終了
```
```sh:結果
$ bun b-1.js
[0.00ms] csv read

$ node b-1.mjs
csv read: 0.088ms
```

#### うひゃぁ。Bunの0.00msてなんだよっｆｒｑ；えおｊｋくぇおｊ

し、失礼いたしました。

それでは、最後に require を import に変えた全体で試してみましょう。

```js:b-5.js または b-5.mjs
console.time('csv read'); // 計測開始
import fs from 'fs';

let path='./zip.csv';

const csv =  fs.readFileSync(path, 'utf8');
const oj=csv.split('\n')
let count=0;

for(let i=0; i<oj.length;i++){
    let line=oj[i].split(',')
    count++;
}
console.log(count);
console.timeEnd('csv read'); // 計測終了
```
```sh:結果
n$ bun  b-5.js
124332
[110.25ms] csv read

$ node b-5.mjs
124332
csv read: 286.079ms
```

まぁ、やはりBun の勝ちでござるな。

あと、Bun は、require より import を使う方が幸せかも？少なくとも fs は。

# 最近 Qiita に書いた Bun 関連の記事10選

https://qiita.com/advent-calendar/2023/bunjs

https://qiita.com/toshirot/items/94961b6dde72be80ab0c

https://qiita.com/toshirot/items/7a0555b46b3a64a4f643

https://qiita.com/toshirot/items/c4d090bc38f9b85d8cdd

https://qiita.com/toshirot/items/4e8e571dd50a45c651f0

https://qiita.com/toshirot/items/e4eb635596ae4f63bdfd

https://qiita.com/toshirot/items/a81f2073e373b0351493

https://qiita.com/toshirot/items/06a992af8cf8aca9ff95

https://qiita.com/toshirot/items/3af83303f95ac7baa546

https://qiita.com/toshirot/items/9f12715e88f0d5060b41