ファイルの各行にUUIDを付加するスニペット
ログ収集ツールのfluentdのuuid_keyを使う場合、ログにUUIDを振る必要がある。
こんなときシェルスクリプトで、whileやfor、uuidgenを組み合わせて、追記していたが、 行が膨大な場合、処理の遅延が気になったので、C言語で処理するプログラムを書いた。
プログラム
Ubuntu環境で、動かした。
依存ライブラリをインストールする。
$ sudo apt install uuid-dev
Cのプログラムは、こんな感じ。
#include <stdio.h> #include <string.h> #include <uuid/uuid.h> int main(int argc, char *argv[]) { FILE *source, *target; char line[256]; uuid_t uuid; char uuid_str[37]; int len; source = fopen(argv[1], "r"); target = fopen(argv[2], "w"); while(fgets(line, 256, source)) { len = strlen(line); if (line[len-1] == '\n') { line[len-1] = 0; } uuid_generate_time_safe(uuid); uuid_unparse_lower(uuid, uuid_str); fprintf(target, "%s %s\n", line, uuid_str); } fclose(source); fclose(target); return 0; }
コンパイルする。
$ gcc -o append_uuid append_uuid.c -luuid
ベンチマーク計測
比較用のファイルを用意する。
$ for i in `seq 10000`; do echo "abc" >> uuid_by_bash.txt; echo "abc" >> uuid_by_c.txt; done $ wc -l uuid_by_bash.txt uuid_by_c.txt 10000 uuid_by_bash.txt 10000 uuid_by_c.txt 20000 total
まずは、Bashでやる場合(これがBashのベストプラクティスかどうかは知らない。。)
$ time cat uuid_by_bash.txt | while read line; do uuid=$(uuidgen); echo "$line $uuid" >> uuid_by_bash.txt.new; done real 0m25.741s user 0m1.268s sys 0m7.632s $ tail -1 uuid_by_bash.txt.new abc 006b69fd-9ad0-4749-afe1-eef73c6ffad0
次は、Cで書いたプログラム。
$ time ./append_uuid uuid_by_c.txt uuid_by_c.txt.new uuid_by_c.txt uuid_by_c.txt.new real 0m0.020s user 0m0.016s sys 0m0.000s $ tail -1 uuid_by_c.txt.new abc d05dc0b5-bad5-11e6-81bd-000c291c1598
クソ速い。