メインコンテンツまでスキップ

最強の圧縮方式について調査

· 約6分
ひかり
Main bloger

結論

結論から。

合計 34 GiB の大量のファイルを圧縮・展開したときの時間とサイズを調べた。

圧縮・アーカイブ作成

方式コマンドrealusersys圧縮後のサイズ
tartar cf large-pkg.tar large-pkg1m19.449s0m6.702s0m48.121s26 GiB
tar.gztar czf large-pkg.tar.gz large-pkg11m33.942s11m18.811s0m55.573s5.5 GiB
LZ4tar cf - large-pkg | lz4 > large-pkg.tar.lz43m33.187s0m53.958s2m57.122s8.6 GiB
zstdtar cf - large-pkg | zstd -T0 -o large-pkg.tar.zst9m13.819s1m45.049s2m43.609s4.8 GiB
bzip2tar cf - large-pkg.1 | bzip2 > large-pkg.tar.bz237m22.743s28m40.329s3m31.000s4.3 GiB
xztar cf - large-pkg | xz > large-pkg.tar.xz125m31.447s124m10.523s5m18.330s3.3 GiB

展開 (解凍)

方式コマンドrealusersys
tartar xf large-pkg.tar2m11.793s0m6.906s2m4.183s
tar.gztar xf large-pkg.tar.gz3m39.544s2m1.189s2m58.317s
tar.gz(gzip)gzip -dc large-pkg.tar.gz | tar xf -3m40.416s2m0.272s3m0.043s
tar.gz(pigz)pigz -dc large-pkg.tar.gz | tar xf -3m53.711s1m38.147s4m42.893s
LZ4lz4 -dc large-pkg.tar.lz4 | tar xf -4m46.576s0m32.174s4m36.055s
zstdzstd -dc large-pkg.tar.zst | tar xf -3m46.419s0m46.533s3m34.668s
bzip2bzip2 -dc large-pkg.tar.bz2 | tar xf -11m31.287s9m52.644s4m17.974s
xzxz -dc large-pkg.tar.xz | tar xf -8m11.527s3m45.562s7m15.109s

小さく大量のファイルを用意

まず、小さく大量のファイルとして、node_modules を用いることとした。

package.json を以下のようにした。パッケージは適当なもの。

package.json
{
"name": "large-pkg",
"version": "1.0.0",
"description": "",
"author": "",
"type": "commonjs",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"dependencies": {
"async": "^3.2.6",
"axios": "^1.13.2",
"bcryptjs": "^3.0.3",
"bluebird": "^3.7.2",
"body-parser": "^2.2.2",
"chalk": "^5.6.2",
"chalk-template": "^1.1.2",
"cheerio": "^1.1.2",
"chokidar": "^5.0.0",
"commander": "^14.0.2",
"cookie": "^1.1.1",
"core-js": "^3.47.0",
"cors": "^2.8.5",
"debug": "^4.4.3",
"dotenv": "^17.2.3",
"express": "^5.2.1",
"fast-glob": "^3.3.3",
"form-data": "^4.0.5",
"glob": "^13.0.0",
"got": "^14.6.6",
"inquirer": "^13.2.0",
"jsonwebtoken": "^9.0.3",
"lodash": "^4.17.21",
"mime": "^4.1.0",
"minimist": "^1.2.8",
"mkdirp": "^3.0.1",
"mkdirp-classic": "^0.5.3",
"mongoose": "^9.1.4",
"ms": "^2.1.3",
"node-fetch": "^3.3.2",
"ora": "^9.0.0",
"passport": "^0.7.0",
"prop-types": "^15.8.1",
"qs": "^6.14.1",
"react": "^19.2.3",
"react-dom": "^19.2.3",
"request": "^2.88.2",
"rimraf": "^6.1.2",
"semver": "^7.7.3",
"sharp": "^0.34.5",
"socket.io": "^4.8.3",
"supports-color": "^10.2.2",
"tslib": "^2.8.1",
"uuid": "^13.0.0",
"ws": "^8.19.0",
"xml2js": "^0.6.2",
"yargs": "^18.0.0"
},
"devDependencies": {
"@babel/cli": "^7.28.6",
"@babel/plugin-transform-runtime": "^7.28.5",
"@babel/preset-env": "^7.28.6",
"@babel/runtime": "^7.28.6",
"autoprefixer": "^10.4.23",
"ava": "^6.4.1",
"babel-core": "^6.26.3",
"babel-loader": "^10.0.0",
"chai": "^6.2.2",
"commitlint": "^20.3.1",
"concurrently": "^9.2.1",
"conventional-changelog": "^7.1.1",
"cross-env": "^10.1.0",
"css-loader": "^7.1.2",
"dotenv-expand": "^12.0.3",
"eslint": "^8.57.1",
"eslint-config-prettier": "^10.1.8",
"eslint-config-standard": "^17.1.0",
"eslint-plugin-import": "^2.32.0",
"eslint-plugin-jsx-a11y": "^6.10.2",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-prettier": "^5.5.5",
"eslint-plugin-react": "^7.37.5",
"husky": "^9.1.7",
"jest": "^30.2.0",
"less": "^4.5.1",
"lint-staged": "^16.2.7",
"mocha": "^11.7.5",
"nodemon": "^3.1.11",
"playwright": "^1.57.0",
"pm2": "^6.0.14",
"postcss": "^8.5.6",
"prettier": "^3.8.0",
"puppeteer": "^24.35.0",
"rollup": "^4.55.1",
"rxjs": "^7.8.2",
"sass": "^1.97.2",
"semantic-release": "^25.0.2",
"sinon": "^21.0.1",
"style-loader": "^4.0.0",
"stylus": "^0.64.0",
"supertest": "^7.2.2",
"tailwindcss": "^4.1.18",
"ts-loader": "^9.5.4",
"ts-node": "^10.9.2",
"typescript": "^5.9.3",
"vite": "^7.3.1",
"vitest": "^4.0.17",
"webpack": "^5.104.1",
"webpack-cli": "^6.0.1",
"webpack-dev-server": "^5.2.3",
"zx": "^8.8.5"
}
}

ここから、以下のコマンドで node_modules を作成する。

npm i

容量を見てみよう。

$ du -h -d1
566M ./node_modules
567M .

これで、小さく大量のファイルが作成されたことがわかる。

node_modules をコピーしてさらに多くのファイルを作成する。

for i in {1..59}; do
echo "node_modules.${i} をコピー中..."
cp -r node_modules "node_modules.${i}"
done

容量を見てみよう。

$ du -h -d1
...
34G .

そこそこ大きい容量となった。

tarball

tarball にする速度を見てみる。

アーカイブ

$ time tar cf large-pkg.tar large-pkg

real 1m19.449s
user 0m6.702s
sys 0m48.121s

アーカイブ後、26 GiB

展開

$ time tar xf large-pkg.tar

real 2m11.793s
user 0m6.906s
sys 2m4.183s

アーカイブと展開はそこそこ速い。

tar.gz

次に、tar.gz で試す。

tar コマンドはアーカイブするコマンドで、gzip は単一のファイルを圧縮するコマンドだ。これを組み合わせて作成されたのが tar.gz ファイルである。 現在では tar コマンドのみで tar.gz ファイルの圧縮と展開が可能だ。(ほかの圧縮形式も同様)

圧縮

$ time tar czf large-pkg.tar.gz large-pkg

real 11m33.942s
user 11m18.811s
sys 0m55.573s

圧縮後: 5.5 GiB

展開

$ time tar xf large-pkg.tar.gz

real 3m39.544s
user 2m1.189s
sys 2m58.317s

tar と gzip で展開

$ time sh -c 'gzip -dc large-pkg.tar.gz | tar xf -'

real 3m40.416s
user 2m0.272s
sys 3m0.043s

速度はほぼ同じ。

並列で展開 (pigz)

$ time sh -c 'pigz -dc large-pkg.tar.gz | tar xf -'

real 3m53.711s
user 1m38.147s
sys 4m42.893s

あまり速度は変わんない。ファイルの読み書き速度がボトルネックとなっているようだ。

bzip2

圧縮

$ time sh -c 'tar cf - large-pkg.1 | bzip2 > large-pkg.tar.bz2'

real 37m22.743s
user 28m40.329s
sys 3m31.000s

圧縮後: 4.3 GiB

圧縮に時間がかかっているが、圧縮率はそこそこ良い。

展開

$ time sh -c 'bzip2 -dc large-pkg.tar.bz2 | tar xf -'

real 11m31.287s
user 9m52.644s
sys 4m17.974s

展開も時間はかかるが、展開率はそこそこ良い。

xz

圧縮

$ time sh -c 'tar cf - large-pkg | xz > large-pkg.tar.xz'

real 125m31.447s
user 124m10.523s
sys 5m18.330s

圧縮後: 3.3 GiB

圧縮率は極めて優秀だが、時間がかかりすぎる。

ネット回線が非常に遅く、ストレージ料金が高く、数年に1度使うようなレアケースではいいかも。

展開

$ time sh -c 'xz -dc large-pkg.tar.xz | tar xf -'

real 8m11.527s
user 3m45.562s
sys 7m15.109s

LZ4

圧縮

$ time sh -c 'tar cf - large-pkg | lz4 > large-pkg.tar.lz4'

real 3m33.187s
user 0m53.958s
sys 2m57.122s

展開

$ time sh -c 'lz4 -dc large-pkg.tar.lz4 | tar xf -'

real 4m46.576s
user 0m32.174s
sys 4m36.055s

zstd

Meta (旧 Facebook) が開発した高速の圧縮方式。

圧縮

$ time sh -c 'tar cf - large-pkg | zstd -T0 -o large-pkg.tar.zst'
/*stdin*\ : 18.57% (27492075520 => 5106239218 bytes, large-pkg.tar.zst)

real 9m13.819s
user 1m45.049s
sys 2m43.609s

展開

$ time sh -c 'zstd -dc large-pkg.tar.zst | tar xf -'
large-pkg.tar.zst : 27492075520 bytes

real 3m46.419s
user 0m46.533s
sys 3m34.668s

Raspberry Pi で cockpit に mkcert を用いて証明書を作成し、サーバー (cockpit) とブラウザに設定する方法

· 約2分
ひかり
Main bloger

動作環境

以下の環境で設定を確認しました。

  • Raspberry Pi 5
  • AlmaLinux

各証明書の意味

  • raspberrypi.pem: サーバー証明書 (公開鍵) この証明書は raspberrypi というホスト名に対して発行された SSL 証明書です。Web ブラウザなどのクライアントがこの証明書を使ってサーバーの正当性を確認します。(サーバーにインストールするやつ)
  • raspberrypi+1.pem: サーバー証明書 (公開鍵)
    この証明書は raspberrypi <IP アドレス> というホスト名に対して発行された SSL 証明書です。同上
  • raspberrypi-key.pem:
    raspberrypi.pem に対応する秘密鍵です。サーバー側で保持し、SSL通信の暗号化・復号に使用されます。絶対に外部に漏らしてはいけません。 (サーバーにインストールするやつ)
  • raspberrypi+1-key.pem:
    raspberrypi+1.pem に対応する秘密鍵です。サーバー側で保持し、SSL通信の暗号化・復号に使用されます。絶対に外部に漏らしてはいけません。 同上
  • rootCA.pem: ローカルルート証明書 (公開鍵)
    mkcert が自動生成したローカルCA (認証局) の証明書です。クライアント (ブラウザなど) にこの証明書をインストールすることで、raspberrypi.pem を信頼できる証明書として扱えるようになります。
  • rootCA-key.pem: ローカル CA の秘密鍵 rootCA.pem に対応する秘密鍵で、mkcert がサーバー証明書 (例: raspberrypi.pem) を署名するために使います。mkcert が内部的に使用するもので、通常は触る必要はありません。

証明書の発行

mkcert コマンドを用いて証明書を発行します。発行後、サーバーに配置します。

mkcert raspberrypi <IP アドレス>

sudo cp raspberrypi+1-key.pem /etc/cockpit/ws-certs.d/raspberrypi.key
sudo cp raspberrypi+1.pem /etc/cockpit/ws-certs.d/raspberrypi.crt
sudo systemctl restart cockpit

ローカルルート証明書の場所を確認

PC にルート証明書をインストールするためのルート CA 証明書の場所を確認します。

mkcert -CAROOT

ルート証明書を PC にコピー

ルート証明書を PC にコピーします。

scp raspberrypi:/home/<USER>/.local/share/mkcert/rootCA.pem .
cp rootCA.pem rootCA.cer

Windows で証明書を登録

rootCA.cer を開き、証明書ストアで「信頼されたルート機関」で証明書を登録します。

Android 端末で証明書を登録

rootCA.pem を端末に移動し設定から登録します。

OpenStreetMap を podman でインストールする方法

· 約1分
ひかり
Main bloger

import

japan-xxx.osm.bpf をホームディレクトリにダウンロードしておく。 その後、以下のコマンドを実行し準備。 volume オプション末尾の :Z は SELinux が稼働している場合に付ける。

/data/region.osm.pbf の部分は変更しないこと。

podman volume create osm-data

podman run -v <ダウンロードした osm.bpf ファイル>:/data/region.osm.pbf:Z -v osm-data:/data/database/ overv/openstreetmap-tile-server import

imoprt 例

podman volume create osm-data

podman run -v <ダウンロードした osm.bpf ファイル>:/data/region.osm.pbf:Z -v osm-data:/data/database/ overv/openstreetmap-tile-server import

run

以下のコマンドでタイルサーバーを実行する。

podman run -p 8080:80 -v osm-data:/data/database/ -v osm-tiles:/data/tiles/ -d overv/openstreetmap-tile-server run

ファイアーウォールの設定を行えば、ネットワーク上からアクセス可能。

バックアップを取る

podman volume export osm-data > osm-data.tar

Raspberry Pi をサーバー代わりにしてサイトへ公開する

· 約2分
ひかり
Main bloger

Raspberry Pi で nginx をセットアップ

# nginx のインストールと有効化
sudo dnf install nginx

# /etc/nginx/nginx.conf の編集
# sudo nano /etc/nginx/nginx.conf

# nginx の開始と有効化
sudo systemctl start nginx
sudo systemctl enable nginx
sudo systemctl status nginx

/etc/nginx/nginx.conf の編集

http { server {} } 内に以下を追加

location / {
return 200 'Hello, world!';
add_header Content-Type text/plain;
}

CloudFlare の設定

  1. https://one.dash.cloudflare.com/ にアクセス。
  2. 「ネットワーク」→「Tunnels」を開く
  3. 「トンネルを追加する」を押す

CloudFlare Tunnels

  1. 「選択する Cloudflared」を押す

Select Cloudflared

  1. 「トンネル名」に適当な名前を入力して、「トンネルを保存」を押す

Save Tunnel Name for Cloudflare

cloudflared のインストール

# cloudflared.repo を /etc/yum.repos.d/ に追加
curl -fsSl https://pkg.cloudflare.com/cloudflared-ascii.repo | sudo tee /etc/yum.repos.d/cloudflared.repo

sudo dnf clean packages

# cloudflared のインストール
sudo dnf install -y cloudflared --nogpgcheck

cloudflared でサービスの起動

sudo cloudflared service install xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

トラフィックのルーティング

ホスト名のサブドメインとドメインと、サービスのタイプ、URL を設定。

alt text

「セットアップを完了する」を押す。

AlmaLinux 10 (Raspberry Pi 5 / GNOME / aarch64) に Mozc をインストールする方法

· 約1分
ひかり
Main bloger

rpm ファイルをダウンロード

  • mozc
  • mozc-gui-tools
  • ibus-mozc

を検索し、rpmfind.net から検索してダウンロードする。

アーキテクチャが正しいかを確かめる。

  • Raspberry Pi 5 の場合は、aarch64
  • 一般的な PC の場合は、x86_64

rpm ファイルの例

  • mozc-2.31.5810.102-160000.1.2.aarch64.rpm
  • mozc-gui-tools-2.31.5810.102-160000.1.2.aarch64.rpm
  • ibus-mozc-2.31.5810.102-160000.1.2.aarch64.rpm

インストール

ダウンロードした rpm ファイルを指定し、dnf コマンドでインストールする。

cd ~/Downloads
sudo dnf install ./mozc-2.31.5810.102-160000.1.2.aarch64.rpm ./mozc-gui-tools-2.31.5810.102-160000.1.2.aarch64.rpm ./ibus-mozc-2.31.5810.102-160000.1.2.aarch64.rpm

ログアウト

一旦ログアウトする。

設定

「設定」→「キーボード」を開き、

  • Japanese (Mozc)
  • Japanese

の順に登録。

設定完了!

GPT-5 を API で叩く

· 約1分
ひかり
Main bloger

GPT-5 が公開されたので、PowerShell で API を叩いてみました。

コード

$uri = "https://api.openai.com/v1/chat/completions"
$headers = @{
"Authorization" = "Bearer $env:OPENAI_API_KEY"
"Content-Type" = "application/json"
}

$body = @{
model = "gpt-5"
messages = @(
@{
role = "user"
content = "ノートと鉛筆の合計は100円。鉛筆はノートより40円安い。鉛筆の値段は?"
}
)
} | ConvertTo-Json -Depth 2

$response = Invoke-RestMethod -Uri $uri -Method Post -Headers $headers -Body $body

foreach($choice in $response.choices){
$choice.message.content
}

出力結果

30円

理由:
- ノートをx円、鉛筆をy円とすると
- x + y = 100
- y = x - 40
- 代入して 2x - 40 = 100 → x = 70 → y = 30
- 確認: 70 + 30 = 100、鉛筆はノートより40円安い。

コマンドを叩いてローカル MCP の動きを見てみる

· 約3分
ひかり
Main bloger

処理の流れ

MCP を使用した場合、LLM クライアントでどのような流れで処理が行われるかを Copilot くんに聞きました。

以下、シーケンス図です。

ここで重要なのは、

  1. ①② ツール定義の取得
  2. ④ ツール定義の送信
  3. ⑦ ツール呼び出し要求
  4. ⑧⑨⑩⑪ ツール呼び出し
  5. ⑫ 実行結果の送信

です。

MCP にかかわる部分は、1. と 4. で、 Function calling とほぼ同じ部分が 2. と 3. と 5. です。

コマンドを叩いて呼び出してみる

ローカル MCP を標準入力で使用してみましょう。

Windows PowerShell を用いてコマンドをたたきます。

ツール一覧を取得

例として @modelcontextprotocol/server-filesystem のツール一覧を取得します。

> @{ jsonrpc = "2.0"; method = "tools/list"; id = 1 } | ConvertTo-Json -Compress | npx @modelcontextprotocol/server-filesystem $HOME | ConvertFrom-Json | ConvertTo-Json -Depth 10
Secure MCP Filesystem Server running on stdio
Allowed directories: [ 'C:\\Users\\hikari' ]
{
"result": {
"tools": [
{
"name": "read_file",
"description": "Read the complete contents of a file from the file system. Handles various text encodings and provides detailed error messages if the file cannot be read. Use this tool when you need to examine the contents of a single file. Only works within allowed directories.",
"inputSchema": {
"type": "object",
"properties": {
"path": {
"type": "string"
}
},
"required": [
"path"
],
"additionalProperties": false,
"$schema": "http://json-schema.org/draft-07/schema#"
}
},
...
]
}
}

tools/list を標準入力で与えることで、ツール一覧を JSON 形式で取得できます。

ツール呼び出し

ツールの情報をもとに呼び出してみます。

> @{ jsonrpc = "2.0"; method = "tools/call"; params = @{name = "read_file"; arguments = @{path = ".gitconfig"}}; id = 2 } | ConvertTo-Json -Compress -Depth 10 | npx @modelcontextprotocol/server-filesystem $HOME | ConvertFrom-Json | ConvertTo-Json -Depth 10
Secure MCP Filesystem Server running on stdio
Allowed directories: [ 'C:\\Users\\hikari' ]
{
"result": {
"content": [
{
"type": "text",
"text": "..."
}
]
},
"jsonrpc": "2.0",
"id": 2
}

Rocky Linux 8.10 を WSL にインストールする

· 約2分
ひかり
Main bloger

Rocky Linux 8.10 のイメージをダウンロードする

$dest = Join-Path $env:TEMP "Rocky-8-Container-Base.latest.x86_64.tar.xz"
Invoke-WebRequest -Uri "https://dl.rockylinux.org/pub/rocky/8/images/x86_64/Rocky-8-Container-Base.latest.x86_64.tar.xz" -OutFile $dest

インポート

wsl --import RockyLinux-8.10 $HOME $dest

passwd のインストール

wsl -d RockyLinux-8.10 -u root dnf update -y `&`& dnf install -y passwd

ユーザーの作成

$username = "hikari" # 好きなユーザー名を設定
wsl -d RockyLinux-8.10 -u root useradd -mG wheel $username
wsl -d RockyLinux-8.10 -u root passwd -d $username # ユーザーのパスワードを消去

sudo のインストール

wsl -d RockyLinux-8.10 -u root dnf update -y `&`& dnf install sudo -y

デフォルトユーザーの設定

$username = "hikari" # 好きなユーザー名を設定
$uid = wsl -d RockyLinux-8.10 id $username -u
if (-not $uid) {
Write-Error "UID の取得に失敗しました。ユーザー '$username' が存在しない可能性があります。"
exit 1
}

$basePath = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Lxss"

$targetKey = Get-ChildItem $basePath | Where-Object {
(Get-ItemProperty $_.PSPath).DistributionName -eq "RockyLinux-8.10"
}
if (-not $targetKey) {
Write-Error "DistributionName 'RockyLinux-8.10' が見つかりませんでした。"
exit 1
}

Set-ItemProperty -Path $targetKey.PSPath -Name "DefaultUid" -Value ([int]$uid)

EPEL の有効化

wsl -d RockyLinux-8.10 -u root dnf update -y `&`& dnf install -y epel-release

起動

wsl -d RockyLinux-8.10

デフォルトのディストリビューションにする場合

wsl --set-default RockyLinux-8.10

FastFetch のインストール

wsl -d RockyLinux-8.10 -u root dnf update -y `&`& dnf install fastfetch

FastFetch の実行

> wsl -d RockyLinux-8.10 -u root fastfetch
__wgliliiligw_, root@DESKTOP-MS-7C56-B550
_williiiiiiliilililw, -------------------------
_%iiiiiilililiiiiiiiiiii_ OS: Rocky Linux 8.10 x86_64
.Qliiiililiiiiiiililililiilm. Host: Windows Subsystem for Linux (2.0.14.0)
_iiiiiliiiiiililiiiiiiiiiiliil, Kernel: 5.15.133.1-microsoft-standard-WSL2
.lililiiilililiiiilililililiiiii, Uptime: 8 mins
_liiiiiiliiiiiiiliiiiiF{iiiiiilili, Packages: 285 (rpm)
jliililiiilililiiili@` ~ililiiiiiL Shell: bash 4.4.20
iiiliiiiliiiiiiili>` ~liililii Display 1: 1920x1080 @ 60Hz
liliiiliiilililii` -9liiiil Display 2: 1920x1080 @ 60Hz
iiiiiliiliiiiii~ "4lili WM: WSLg (Wayland)
4ililiiiiilil~| -w, )4lf Terminal: Windows Terminal
-liiiiililiF' _liig, )' CPU: AMD Ryzen 9 3900X (24) @ 3.800018 GHz
)iiiliii@` _QIililig, GPU: Microsoft Corporation Basic Render Driver
)iiii>` .Qliliiiililw Memory: 458.57 MiB / 62.76 GiB (0%)
)<>~ .mliiiiiliiiiiil, Disk (/): 51.72 GiB / 1007 GiB (5%)
_gllilililiililii~ Locale: C.UTF-8
giliiiiiiiiiiiiT`
-^~$ililili@~~' ████████████████████████
████████████████████████

RHEL 10.0 で epel-release を有効にする

· 約1分
ひかり
Main bloger
sudo dnf update -y
sudo subscription-manager repos --enable codeready-builder-for-rhel-10-x86_64-rpms
sudo dnf install https://dl.fedoraproject.org/pub/epel/epel-release-latest-10.noarch.rpm