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 等编写的任何东西。内核将管理管道之间的缓冲区,这意味着大部分深奥、糟糕的工作已经完成。
我有一个有点大的文本文件(大约 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 等编写的任何东西。内核将管理管道之间的缓冲区,这意味着大部分深奥、糟糕的工作已经完成。