fugafuga.write

日々のログ

'no'コマンドについての本当にちょっとした話

この記事に触発されて、Elixir の練習として似たようなコマンドを作った。

Unixコマンド”yes”についてのちょっとした話 | コンピュータサイエンス | POSTD

この世の全てを否定するコマンドno

記事内ではyesコマンドが扱われていたがそのまま作ってもしょうもないので、noコマンドを作ることにした。 仕様はほぼyesと同じ。標準出力に永久にnを出力し続ける。

こんな感じで使えるようにする。

> no
n
n
n
n
n
n
n
...

または、

> no | sh work_a_lot.sh

annoying boss に

「安月給でもっと働け!!プロ意識をもて!!やりがいで駆動しろ!!」と言われましたか?

そういう時にこのコマンドが役に立つはずです。

※ 効果には個人差があります

さっそく作る

環境

> elixir -v
Erlang/OTP 20 [erts-9.1.1] [source] [64-bit] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false] [dtrace]

Elixir 1.5.2

プロジェクト作成

> mix new no
> cd no

mix.exs修正

Elixir で実行可能ファイルを作成するには、escriptを使えとのこと

Erlang -- escript

  • line:9 escript を使用するためにモジュールを指定
  • line:22-24 モジュール名などを返す関数を書くのが良さげ

mix.exs

ここで指定した module の No.main/1がエントリポイントになる

実装

普通にループするだけじゃあしょうもないので、プロセスをたくさん生成してそれぞれがnを出力し続けられるようなオプション-pを追加した。 あと、その並列実行の様を観測できるように-dでPIDを見られるようにもした。

OptionParser めっちゃ便利。

こうやったほうがCOOLだよ!などがあれば教えてもらえるととても嬉しいです。

no

ビルド

実装が済んだらビルド mix.exsがあるディレクトリで実行する

> mix escript.build

カレントディレクトリに実行可能ファイルが生成されるはず

実行

カレントディレクトリに

> ./no -p 100
n
n
n
n
n
...

とりあえず動いている

デバッグオプション有り

> ./no -p 100 -d
{"n from process no.47", #PID<0.122.0>}
{"n from process no.47", #PID<0.122.0>}
{"n from process no.47", #PID<0.122.0>}
{"n from process no.40", #PID<0.115.0>}
{"n from process no.47", #PID<0.122.0>}
...

やったぜ

速度的にどうなの

速度が気になったので計測してみた

> ./no | pv -r > /dev/null
[93.7KiB/s]

yesコマンドはというと、

> yes | pv -r > /dev/null
[31.6MiB/s]

noコマンド、桁違いに遅くて笑っちゃう!!!

まあまあ落ち着け、並行処理で逆転だぜ!

> ./no -p 100 | pv -r > /dev/null
[1.12KiB/s]

より遅くなるってどういうことなの...

まとめ

  • 言語の練習題材としてLinuxコマンドを再実装するのは良い
    • 機能のサイズ的に手頃なのが多い
  • |>で処理繋いでいくのは気持ち良い
  • なんで遅くなるのかわからん
    • 気が向いたら調べる
  • Hex への登録

気が向いたら続く。

github.com

(参考)

プログラミングElixir

プログラミングElixir