ロケールでソートパフォーマンスが全然違う件

TL;DR

  • LANG=Cが最速
  • fish
    • C.UTF-8はCと比べてrealで1.3倍、userで1.8倍遅い
    • ja_JP.UTF-8はCと比べてrealで2.4倍、userで6.3倍遅い
      • realは実行時間、userはCPU処理時間合計(マルチコアでパラレル処理してると合計でrealより長くなるときがある)(※system=OS側処理, user=アプリ側処理)
  • bash
    • C.UTF-8はCと比べてrealで1.1倍、userで1.4倍遅い
    • ja_JP.UTF-8はCと比べてrealで2.1倍、userで4.6倍遅い
  • 繰り返し計測してるとタイミングでバラつきがある(キャッシュ有無とかはもちろん考慮した上で)ので参考まで

結果1(fish)

  • コマンド: for i in (seq 1 10); time sort 2000-02_pbp.csv > /dev/null; end
  • timeコマンドの実行結果で1秒未満はmillis、1秒以上はsec表記だが、一覧にするためmillisに統一
    • その影響でsec表記の値はミリ秒の一桁目が0埋めされてる
    • そのためja_JP.UTF-8列の値が一桁目が0なのはsec表記をミリ秒表記に統一するときにミリ秒の一桁目がゼロ埋めされた影響
  • 1回目はキャッシュがないので遅くなりがち、と思ったけど遅いのja_JP.UTF-8だけだ

Executed in(=real)(単位:sec)

CC.UTF-8ja_JP.UTF-8
0.7380.71232.600
0.6690.8051.300
0.6101.0001.380
0.6190.8951.420
0.5200.8841.620
0.4880.8921.470
0.7210.8931.280
0.8261.0401.380
0.7980.8691.620
0.7280.7732.910

User(単位:sec)

CC.UTF-8ja_JP.UTF-8
0.6570.92448.18
0.7781.234.31
0.6581.334.68
0.6441.374.82
0.61.344.59
0.5871.284.92
0.6681.374.69
0.8011.594.88
0.8761.374.43
0.9431.254.61

結果2(bash)

  • fishのtimeコマンドがなんか見づらかった(以下)
    • 1秒未満だとmillis, 1秒以上だとsec表記、パッとは見やすいけど一覧にして比較しづらい
    • Executed inの値がrealと同義でいいんだっけ??(体感的には合ってる)
    • ust timeがExetuted inより大幅に長いし実際に10秒かかってないんだけど何?
      • たぶんマルチコアでパラレル処理してるCPU時間の全コア合計の処理時間なのでrealを超えてくる
    • fish/externalの分類、細かく表示してくれるのはいいけどいらない..
________________________________________________________
Executed in    3.84 secs    fish           external
   usr time   10.05 secs    0.00 micros   10.05 secs
   sys time    1.67 secs  378.00 micros    1.67 secs
  • なのでbashで再実行
  • bashだと全然早い。てかfish遅すぎないか

real(単位:sec)

CC.UTF-8ja_JP.UTF-8
0.3260.3570.619
0.290.3270.6
0.2570.3230.602
0.2720.3310.592
0.2940.3360.628
0.2930.3290.604
0.2880.320.606
0.2970.320.623
0.2840.3370.63
0.2920.3270.625

user(単位:sec)

CC.UTF-8ja_JP.UTF-8
0.4460.6642.026
0.4520.6212.008
0.3920.7052.022
0.5070.6532.018
0.4620.6992.165
0.4940.6632.097
0.440.6512.05
0.4430.6462.235
0.4850.6822.151
0.3950.6752.23

average(fish/bash, real/user)(単位:sec)

  • 時間増(倍数)、処理性能減(%)はCと比較した数値
  • real/userでそれぞれfish/bashのaverageを記載
  • 1回目はキャッシュ暖機として捨てて、2回目~10回目のaverageを取得

real

fish

CC.UTF-8ja_JP.UTF-8
sec0.660.891.60
時間増(倍数)1.342.4
処理性能(%)7441

bash

CC.UTF-8ja_JP.UTF-8
sec0.290.330.61
時間増(倍数)1.142.14
処理性能(%)8746

user

fish

CC.UTF-8ja_JP.UTF-8
sec0.731.354.66
時間増(倍数)1.856.39
処理性能(%)5415

bash

CC.UTF-8ja_JP.UTF-8
sec0.450.672.11
時間増(倍数)1.474.66
処理性能減(%)6721

簡単に要約

  • real(実際の実行時間)で、C.UTF-8はCより1.1~1.3倍遅く、ja_JP.UTF-8はCより2.1~2.4倍遅い
  • user(CPUコアの合計処理時間)だともっと顕著で、C.UTF-8はCより1.4~1.8倍処理時間が必要で、ja_JP.UTF-8はCより4.6~6.3倍処理時間が必要

その他

  • 最初測定してて、185MBのファイルのsortにfishで5秒かかってた
  • 途中で(いつも通り)WSLのCPU使用率が高止まりし始めたので、WSLを再起動したら、同じ処理が1秒未満で終わるようになったため、ファイルサイズを1.8GBに増加させて再計測
  • その再計測結果を記載

キャッシュについて

fishのja_JP.UTF-8で1回目遅いのが顕著だった

ロケールC, C.UTF-8ではそもそも処理が早いのもあってキャッシュの影響を感じないことが多い

何度もやると途中で微妙に遅くなったりもするけどホストOS上で色々動いてる影響を受けると思うので平均的に見るのが大事

コマンドめも

C

# localectl set-locale LANG=C && export LANG=C && localectl && locale
   System Locale: LANG=C
       VC Keymap: n/a
      X11 Layout: us
       X11 Model: pc105
LANG=C
LANGUAGE=
LC_CTYPE="C"
LC_NUMERIC="C"
LC_TIME="C"
LC_COLLATE="C"
LC_MONETARY="C"
LC_MESSAGES="C"
LC_PAPER="C"
LC_NAME="C"
LC_ADDRESS="C"
LC_TELEPHONE="C"
LC_MEASUREMENT="C"
LC_IDENTIFICATION="C"
LC_ALL=

C.UTF-8

# localectl set-locale LANG=C.UTF-8 && export LANG=C.UTF-8 && localectl && locale
   System Locale: LANG=C.UTF-8
       VC Keymap: n/a
      X11 Layout: us
       X11 Model: pc105
LANG=C.UTF-8
LANGUAGE=
LC_CTYPE="C.UTF-8"
LC_NUMERIC="C.UTF-8"
LC_TIME="C.UTF-8"
LC_COLLATE="C.UTF-8"
LC_MONETARY="C.UTF-8"
LC_MESSAGES="C.UTF-8"
LC_PAPER="C.UTF-8"
LC_NAME="C.UTF-8"
LC_ADDRESS="C.UTF-8"
LC_TELEPHONE="C.UTF-8"
LC_MEASUREMENT="C.UTF-8"
LC_IDENTIFICATION="C.UTF-8"
LC_ALL=

ja_JP.UTF-8

# localectl set-locale LANG=ja_JP.UTF-8 && export LANG=ja_JP.UTF-8 && localectl && locale
   System Locale: LANG=ja_JP.UTF-8
       VC Keymap: n/a
      X11 Layout: us
       X11 Model: pc105
LANG=ja_JP.UTF-8
LANGUAGE=
LC_CTYPE="ja_JP.UTF-8"
LC_NUMERIC="ja_JP.UTF-8"
LC_TIME="ja_JP.UTF-8"
LC_COLLATE="ja_JP.UTF-8"
LC_MONETARY="ja_JP.UTF-8"
LC_MESSAGES="ja_JP.UTF-8"
LC_PAPER="ja_JP.UTF-8"
LC_NAME="ja_JP.UTF-8"
LC_ADDRESS="ja_JP.UTF-8"
LC_TELEPHONE="ja_JP.UTF-8"
LC_MEASUREMENT="ja_JP.UTF-8"
LC_IDENTIFICATION="ja_JP.UTF-8"
LC_ALL=

ソート計測コマンド

fish

for i in (seq 1 10); time sort 2000-19_pbp.csv > /dev/null; end

bash

# for i in $(seq 1 10); do time sort 2000-02_pbp.csv > /dev/null; done

環境

  • Windows10+WSL2+Ubuntu22.04
  • ファイル(1.8GB CSV)
# ls -Alh /tmp/2000-19_pbp.csv
-rw-r--r-- 1 user user 1.8G Aug 30 12:53 /tmp/2000-19_pbp.csv