ls とls -lの速度比較

に公開

はじめに

lsコマンドでファイルやディレクトリの確認をしていますが、-lのオプションをつけると差はどのようになるのでしょうか。気になったので簡単に実験してみました。

マシンスペック

MacBook Air M2 arm64
Docker上で実施

準備

ディレクトリの作成

mkdir -p ~/ls_bench/{build,logs,src}
cd ~/ls_bench

解析用のpythonスクリプトを作成しておきます。

# analyse.py
import json, pandas as pd, matplotlib.pyplot as plt, sys, pathlib
d = json.load(open('/logs/time.json'))
df = pd.DataFrame(d['results'])
df[['command','mean','stddev']].to_csv('/logs/time.csv', index=False)
df.plot.bar(x='command', y='mean', legend=False)
plt.title('Execution time on 10k files')
plt.ylabel('seconds')
plt.tight_layout()
plt.savefig('/logs/time.png')

Dockerfileの作成・ビルド

FROM ubuntu:22.04

RUN apt-get update && DEBIAN_FRONTEND=noninteractive \
    apt-get install -y --no-install-recommends \
        strace             \
        perf-tools-unstable \
        hyperfine          \
        build-essential    \
        git less time      \
        python3 python3-pip \
    && rm -rf /var/lib/apt/lists/*

WORKDIR /work

COPY analyse.py /work/
docker build -t ls_bench .
docker run --rm -it \
  --name ls_lab \
  --privileged \
  -v "$HOME/ls_bench/logs":/logs \
  -v "$HOME/ls_bench/src":/src \
  ls_bench /bin/bash

コンテナ内で実験ディレクトリを用意

mkdir -p /tmp/bench/huge && cd /tmp/bench/huge
seq 1 10000 | xargs -I{} touch f_{}

実験

実行時間測定

cd /tmp/bench/huge
hyperfine 'ls' 'ls -l' -w 3 -r 10 \
          --export-markdown /logs/time.md \
          --export-json      /logs/time.json
hyperfine 'ls' 'ls -l' -w 3 -r 10 \
          --export-markdown /logs/time.md \
          --export-json      /logs/time.json
Benchmark 1: ls
  Time (mean ± σ):       4.1 ms ±   0.7 ms    [User: 2.0 ms, System: 2.1 ms]
  Range (min  max):     3.5 ms …   5.8 ms    10 runs
 
  Warning: Command took less than 5 ms to complete. Results might be inaccurate.
 
Benchmark 2: ls -l
  Time (mean ± σ):      19.4 ms ±   1.0 ms    [User: 6.6 ms, System: 12.9 ms]
  Range (min  max):    18.7 ms …  21.9 ms    10 runs
 
Summary
  'ls' ran
    4.73 ± 0.84 times faster than 'ls -l'

straceでsyscallを見る

strace -c -o /logs/ls.raw ls 1>/dev/null
head /logs/ls.raw
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 18.78    0.000694         347         2           getdents64
 17.51    0.000647         129         5           read
 11.80    0.000436         436         1           execve
 10.61    0.000392          65         6           openat
  9.85    0.000364          26        14           mmap
  5.22    0.000193          24         8           mprotect
  4.44    0.000164          82         2         2 statfs
  4.44    0.000164          23         7           newfstatat
strace -c -o /logs/ls_l.raw ls -l 1>/dev/null
head /logs/ls_l.raw
% time     seconds  usecs/call     calls    errors syscall
------ ----------- ----------- --------- --------- ----------------
 52.20    0.166379          16     10000           statx
 24.88    0.079297           7     10000     10000 lgetxattr
 22.00    0.070118           7     10000     10000 getxattr
  0.54    0.001715         155        11           getdents64
  0.06    0.000199          13        15           close
  0.06    0.000177          19         9           read
  0.05    0.000166          11        14           newfstatat
  0.04    0.000137          34         4         4 connect

Pythonで簡易分析

command mean stddev
ls 0.00371396088 0.0005009406445877150
ls -l 0.01786725238 0.0006227547928881170

まとめ

今回はlsとls-lの比較をしてみました。皆さんの学習の一助になれば幸いです。

Discussion