Python
C
Linux
UNIX
yes

yesコマンドをいろいろ実装

はじまり

yesコマンドに関する記事をたまたま読んだのでちょっとやってみた。
Unixコマンド”yes”についてのちょっとした話 | コンピュータサイエンス | POSTD
私は標準入力のロックはやっていません。
print系の関数だと可変引数のサポートが邪魔しそうなので基本的にwriteを使っています。

とりあえず

私のArchLinuxにビルトインのyesコマンド(GNU coreutils 8.29)

$ yes | pv -r > /dev/null

8.63GiB/sくらい

C

gcc(7.3.0)で特に最適化とか入れてません

バッファなし

#include <unistd.h>

#define LEN 2

int main() {

    char yes[LEN] = "y\n";

    while (1) {
        write(1, yes, LEN);
    }
}

4.44MiB/sくらい
思ってたより遅い

バッファ有り(8KB)

#include <unistd.h>
#include <stdlib.h>
#include <string.h>

#define BUFSIZE 8192
#define LEN 2

int main() {
    char *buf = malloc(BUFSIZE);

    int i;
    char yes[LEN] = "y\n";

    for (i = 0; i < BUFSIZE; i += LEN) {
        memcpy(buf + i, yes, sizeof(char) * LEN);
    }

    while (1) {
        write(1, buf, BUFSIZE);
    }
}

8.85GiB/sくらい
あれ、これ変なメモリに書き込んでるような
ビルトインのyesよりちょっと速いのはバッファサイズの関係かなと

Python

3.6.4

バッファなし

import sys

while True:
    sys.stdout.write('y\n')

14.2MiB/sくらい
Cのバッファなしより速い

バッファ有り(8KB)

import sys

BUF_SIZE = 8192

yes = ''
while len(yes) <= BUF_SIZE:
    yes += 'y\n'

while True:
    sys.stdout.write(yes)

4.07GiB/sくらい
インタプリタの割に結構早い

本命のシェルスクリプトでやってみた

バッファなし

$ while true; do echo y; done | pv -r > /dev/null 

890KiB/sくらい

バッファ有り(8KBのファイル)

$ for i in `seq 4096`; do echo y; done > yes8kb.txt; while true; do cat yes8kb.txt; done | pv -r > /dev/null

2.93MiB/sくらい

無理矢理(1GBのファイルを作ってやってみた)

$ for i in `seq 524288`; do echo y; done > yes1mb.txt; for i in `seq 1024`; do cat yes1mb.txt; done > yes1g.txt; while true; do cat yes1g.txt; done | pv -r > /dev/null

4.93GiB/sくらい

感想

シェルスクリプトcatコマンドが健闘
もっといい書き方がありそう