Node.js (V8) パフォーマンス比較
普段プログラムを実行してるとき ソフトやブラウザのタブをあれこれ開いてても重くならないくらいのスペックの PC (Windows) で動かしたり VM の最低限度の環境で動かしたりしてもあまり速度差を感じません
感じるときといえばディスク速度が遅い場合に npm ライブラリの初期ロードが遅いくらいです

CPU だけに依存する処理なら意外とどこでも変わらないのかと思って⇩のコードをいくつかの環境で実行してみました

node -e "for(let x=0;x<5;x++){console.time(x); for(let i=0,j=0;i<1000000;i++) j+=i; console.timeEnd(x);}"

VM 上の Fedora 31 (Node.js 13.5)

0: 16.607ms
1: 8.044ms
2: 0.962ms
3: 0.949ms
4: 0.99ms

VM 上の Fedora 31 (Node.js 12.16.1)

0: 13.867ms
1: 5.012ms
2: 0.960ms
3: 0.953ms
4: 0.954ms

メインの Windows 10 (Node.js 12.13)

0: 4.398ms
1: 3.273ms
2: 1.232ms
3: 1.186ms
4: 1.192ms

メインの Windows 10 (Chrome 80)

0: 4.19091796875ms
1: 3.22216796875ms
2: 1.18603515625ms
3: 1.219970703125ms
4: 1.222900390625ms

ノート PC Windows 7 (Node.js 12.6)

0: 5.465ms
1: 4.070ms
2: 0.975ms
3: 0.976ms
4: 0.962ms

Fedora と同じホストに置いてる CentOS (Node.js 10.14)

0: 5.388ms
1: 3.839ms
2: 1.214ms
3: 1.200ms
4: 1.201ms

結果は数回実行して結果が特別外れたものじゃないことを確認してから適当に 1 つ取り出してます

同じ Windows だと Node.js も Chrome もほぼ一緒
Windows と Fedora を比べると Fedora は最初 2 回は遅めで以降は少し Windows よりも高速です
いまいちよくわからない結果です
CentOS のものは Windows よりでした

特別スペックが高い(低い)CPU のマシン使ったりしなければあんまり差はでないようです
Node.js のバージョン差のほうが大きいかも
PARTITION BY って速いの?
SQL でグループごとの最大値の行がほしいとき
単純にやると group by して最大値の値を取り出してそれで where するという 2 段階な考え方

window 関数がいいよっという紹介をみたので 調べてみるとグループごとにソートしてランクとか順番のデータの列を作ることができるみたい
便利そうだけど対象テーブルの行全部にランクの列を追加した一時テーブル作ってそこから検索ってあんまり速くなさそう

気になったので実際に試してみた
データは 30000 件ちょっと
id 列が主キーで group_id 列はインデックスあり

PARTITION BY
explain analyze
select "id", "group_id"
from (select "id", "group_id", row_number() OVER (PARTITION BY group_id ORDER BY id DESC) as n from "tbl") as "sub"
where "n" = 1

"Subquery Scan on sub (cost=3678.01..4868.84 rows=183 width=8) (actual time=29.683..41.953 rows=3 loops=1)"
" Filter: (sub.n = 1)"
" Rows Removed by Filter: 36705"
" -> WindowAgg (cost=3678.01..4410.83 rows=36641 width=16) (actual time=29.681..40.401 rows=36708 loops=1)"
" -> Sort (cost=3678.01..3769.61 rows=36641 width=8) (actual time=29.671..31.515 rows=36708 loops=1)"
" Sort Key: tbl.group_id, tbl.id DESC"
" Sort Method: quicksort Memory: 3087kB"
" -> Seq Scan on tbl (cost=0.00..900.41 rows=36641 width=8) (actual time=0.024..7.945 rows=36708 loops=1)"
"Planning time: 0.178 ms"
"Execution time: 42.396 ms"

MAX
explain analyze
select * from tbl where id = ANY (select max(id) from tbl group by group_id)

"Nested Loop (cost=1083.97..1108.64 rows=3 width=80) (actual time=15.348..15.352 rows=3 loops=1)"
" -> HashAggregate (cost=1083.68..1083.71 rows=3 width=4) (actual time=15.331..15.332 rows=3 loops=1)"
" Group Key: max(tbl_1.id)"
" -> HashAggregate (cost=1083.62..1083.64 rows=3 width=8) (actual time=15.327..15.328 rows=3 loops=1)"
" Group Key: tbl_1.group_id"
" -> Seq Scan on tbl tbl_1 (cost=0.00..900.41 rows=36641 width=8) (actual time=0.020..5.036 rows=36708 loops=1)"
" -> Index Scan using tbl_pkey on tbl (cost=0.29..8.31 rows=1 width=80) (actual time=0.005..0.005 rows=1 loops=3)"
" Index Cond: (id = (max(tbl_1.id)))"
"Planning time: 0.410 ms"
"Execution time: 15.421 ms"

plan 的には PARTITION BY のほうが速いけど実際の結果は MAX のほうが速かった
何回かやっても一緒

短いし速いしなら MAX でよさそう
長い文字列だと処理遅くなる?
画像ファイルとかのバイナリの base64 文字列を扱ってると ただの文字列でも普段使うものの何百や何万倍もの文字数になってます
そう言えば文字列ってオブジェクトじゃなくてプリミティブ
関数の引数に渡したり受け取ったりを繰り返すと 多少は遅くなるのかな

C レベルでいえば ポインタで最初だけ渡して全コピーはしないはず
JavaScript (V8) みたいな最適化が強力な言語だと ただ受け渡しするだけなら文字列の長さなんて関係ない……はず
とはいえ一応試してみることに

function x(s, i) {
if(i > 300) {
return s
}
return y(s, i + 1)
}

function y(s, i) {
return z(s, i + 1)
}

function z(s, i) {
return x(s, i + 1)
}

const shortstr = "short"
const longstr = Math.random().toString().slice(2).repeat(1024 * 1024 * 30)

function measure(name, value){
console.time(name)
for(let i=0;i<100000;i++) {
console.assert(x(value, 0) === value)
}
console.timeEnd(name)
}

measure("s", shortstr)
measure("l", longstr)
measure("s", shortstr)
measure("l", longstr)
measure("s", shortstr)
measure("l", longstr)

結果は

s: 23.27099609375ms
l: 17.584228515625ms
s: 12.656982421875ms
l: 11.31884765625ms
s: 10.472900390625ms
l: 11.520751953125ms

1 回目だけ遅いのはいつものことなので みるのは 2 つ目以降
短いほうが速かったり 長いほうが速かったりで違いも誤差レベル
文字数が多くても 特に気にする必要はなさそう

ちなみに longstr.length は 503,316,480 (だいたい 500 MB) でした
そんなメモリ取って大丈夫かなと思ったけど Chrome のタスクマネージャで見る限りメモリ消費量は特に増えてなし
repeat を使ってるから最適化されてるのかな