Base64 逐行编码更快的方式

Base64 encoding line by line faster way

我有一个有点大的文本文件(大约 10GB),它可以毫无问题地存储在内存中。我的目标是将每一行转换为 base64 字符串。目前我的方法需要永远并且似乎无法完成,因为它是单线程的。

while read line; do echo -n -i $line | base64 >> outputfile.txt; done < inputfile.txt

有人可以提示我如何更快地完成吗?该解决方案每小时创建大约 100MB(因此完成时间为 100 小时)CPU 使用率为 5%,而且磁盘使用率也非常低。

看来我对控制字符有误解... 所以我包含了一个示例文本文件,以及输出应该如何(chepner 用 chomp 是正确的):

示例输入:

Банд`Эрос
testè!?£$
``
▒``▒`

示例输出:

user@monster ~ # head -n 5 bash-script-output.txt
0JHQsNC90LRg0K3RgNC+0YE=
dGVzdMOoIT/CoyQ=
YGA=
4paSYGDilpJg

user@monster ~ # head -n 5 perl-without-chomp.txt
0JHQsNC90LRg0K3RgNC+0YEK
dGVzdMOoIT/CoyQK
YGAK
4paSYGDilpJgCg==

user@monster ~ # head -n 5 perl-chomp.txt
0JHQsNC90LRg0K3RgNC+0YE=
dGVzdMOoIT/CoyQ=
YGA=
4paSYGDilpJg

所以样本总是比人工声明更好 ;=)

只打开一次输出文件可能会有一点帮助:

while IFS= read -r line; do echo -n $line | base64; done < inputfile.txt > outputfile.txt

bash 在这里不是一个好的选择,但是,有两个原因:迭代文件开始时很慢,并且您正在为每一行开始一个新的过程。一个更好的主意是使用一种具有用于计算 base64 值的库的语言,以便所有事情都在一个进程中处理。使用 Perl 的示例

perl -MMIME::Base64 -ne 'print encode_base64($_)' inputfile.txt > outputfile.txt

不要使用 perl 或任何其他 dyn 类型的语言来处理 10G 的文本,尤其是在以下情况下:受限于串行处理,预计源负载会随着时间的推移而增加 and/or 有一些 SLA大约处理时间。

如果顺序无关紧要,那么肯定会绕过高级语言方法,因为您可以免费并行处理,只需使用 shell 和 posix 组件。

$ printf "%s\n" one two three
one
two
three
$ printf "%s\n" one two three \
> | xargs \
>      -P3 `# three parallel processes` \
>      -L1 `# use one line from stdin` \
>     -- sh -c 'echo $@ | base64' _ 
b25lCg==
dHdvCg==
dGhyZWUK

即使顺序(读取的、处理的、写入的)是一个约束,我仍然会利用可用的多核并将工作扇出到多个处理程序,然后扇入到一些减速器-像,单进程。

# add line number to each line
$ printf "%s\n" one two three | nl
     1  one
     2  two
     3  three
# base64 encode second column
$ printf "%s\n" one two three \
>     | nl \
>     | xargs -P3 -L1 sh -c \
>       'echo  | base64 | xargs printf "%s %s\n" ""' _
2 dHdvCg==
1 b25lCg==
3 dGhyZWUK
# sort based on numeric value of first col
$ printf "%s\n" one two three \
>     | nl \
>     | xargs -P3 -L1 sh -c \
>       'echo  | base64 | xargs printf "%s %s\n" ""' _ \
>     | sort -k1 -n
1 b25lCg==
2 dHdvCg==
3 dGhyZWUK

所有这些方法都将扩展到可用内核的数量,并且在文本处理方面,所有繁重的工作都由古老的 c 二进制文件完成,这将胜过其他任何东西。

如果你是一个 satist,在 C 中完成整个事情,但我可以保证上面的内容将胜过用 perl、python、ruby 等编写的任何东西。内核将管理管道之间的缓冲区,这意味着大部分深奥、糟糕的工作已经完成。