先日試したこのベンチのどの行が速いのかちょっと確かめてみたくなった。
このコードは「郵便局の郵便番号データ 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
準備
共通の作業
$ mkdir read-zip-csv_bun
$ cd read-zip-csv_bun
# 郵便番号データをコピーする
$ cp <ファイルへのパス>/zip.csv ./
# 下記の共通read.jsを書く
$ vi read.js
$ mkdir read-zip-csv_node
$ cd read-zip-csv_node
# 郵便番号データをコピーする
$ cp <ファイルへのパス>/zip.csv ./
# 下記の共通read.jsを書く
$ vi 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
$ bun read.js
124332
[124.22ms] csv read
noden用ディレクトリでの作業
at ./read-zip-csv_node
$ node read.js
124332
csv read: 290.21ms
ここから順にやっていきます
console.time('csv read'); // 計測開始
const fs = require('fs');
console.timeEnd('csv read'); // 計測終了
bun a-1.js
[12.05ms] csv read
$ node a-1.js
csv read: 3.343ms
a-1.js
require('fs')
bun: 12.05ms
node: 3.343ms ◎の勝ち
console.time('csv read'); // 計測開始
const fs = require('fs');
let path='./zip.csv';
const csv = fs.readFileSync(path, 'utf8');
console.timeEnd('csv read'); // 計測終了
$ bun a-2.js
[41.19ms] csv read
$ node a-2.js
csv read: 137.513ms
a-1.jsとa-2.jsの差分
fs.readFileSync
bun: 29.14ms ◎bunの勝ち
node: 134.17ms
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'); // 計測終了
$ bun a-3.js
[51.03ms] csv read
$ node a-3.js
csv read: 165.209ms
a-2.jsとa-3.jsの差分
.split
bun: 9.84ms ◎bunの勝ち
node: 27.696ms
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'); // 計測終了
$ bun a-4.js
[122.76ms] csv read
$ node a-4.js
csv read: 285.202ms
a-3.jsとa-4.jsの差分
for
bun: 71.73ms ◎bunの勝ち
node: 119.993ms
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'); // 計測終了
$ bun a-5.js
124332
[123.30ms] csv read
$ node a-5.js
124332
csv read: 289.192ms
a-4.jsとa-5.jsの差分
console.log
bun: 0.54ms ◎bunの勝ち
node: 3.99ms
まとめ
require('fs')の読み込み以外は Bun の勝ちだった。全体通してはa-5.jsでみたとおりほぼ 2.3倍の差がついた。
require('fs')は、Node.jsもビルトインモジュールなので速いのだろうか。これを importにしたらどうなるのかと思い、これだけ試してみた。
console.time('csv read'); // 計測開始
import fs from 'fs'; //import分に変えてみる
console.timeEnd('csv read'); // 計測終了
console.time('csv read'); // 計測開始
import fs from 'fs'; //import分に変えてみる
console.timeEnd('csv read'); // 計測終了
$ bun b-1.js
[0.00ms] csv read
$ node b-1.mjs
csv read: 0.088ms
うひゃぁ。Bunの0.00msてなんだよっfrq;えおjkくぇおj
し、失礼いたしました。
それでは、最後に require を import に変えた全体で試してみましょう。
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'); // 計測終了
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選