快速md5sum数百万string在Bash / Ubuntu的

我需要在Ubuntu的bash脚本中有300万左右的MD5总和。 300万string – > 300万个MD5哈希。 微不足道的实现每个string大约需要0.005秒。 那已经过了4个小时了。 存在哪些更快的select? 有没有办法将string组合成md5sum?

#time md5sum running 100 times on short strings #each iteration is ~0.494s/100 = 0.005s time (for i in {0..99}; do md5sum <(echo $i); done) > /dev/null real 0m0.494s user 0m0.120s sys 0m0.356s 

一个好的解决scheme将包括一个bash / Perl脚本,它接受来自stdin的string列表并输出他们的MD5哈希列表。

在C(或Perl或Python)中使用许多md5实现中的任何一个都不难 – 在它的核心上,md5是一个从字符向量到字符向量的散列函数。

因此,只需编写一个外部程序,读取您的300万个字符串,然后将它们一个接一个地输入到您选择的md5实现中。 这样,你有一个程序启动,而不是300万,这一个单独将节省您的时间。

FWIW在一个项目中,我使用了Christophe Devine的md5实现(C语言),还有OpenSSL,我相信CPAN也会有一些Perl的。

编辑:好的,无法抗拒。 我提到的md5实现例如在这个小的tarball里面。 把文件md5.c替换成(#ifdef'ed) main()

 int main( int argc, char *argv[] ) { FILE *f; int j; md5_context ctx; unsigned char buf[1000]; unsigned char md5sum[16]; if( ! ( f = fopen( argv[1], "rb" ) ) ) { perror( "fopen" ); return( 1 ); } while( fscanf(f, "%s", buf) == 1 ) { md5_starts( &ctx ); md5_update( &ctx, buf, (uint32) strlen((char*)buf) ); md5_finish( &ctx, md5sum ); for( j = 0; j < 16; j++ ) { printf( "%02x", md5sum[j] ); } printf( " <- %s\n", buf ); } return( 0 ); } 

建立一个简单的独立程序,如在

 /tmp$ gcc -Wall -O3 -o simple_md5 simple_md5.c 

然后你得到这个:

 # first, generate 300,000 numbers in a file (using 'little r', an R variant) /tmp$ r -e'for (i in 1:300000) cat(i,"\n")' > foo.txt # illustrate the output /tmp$ ./simple_md5 foo.txt | head c4ca4238a0b923820dcc509a6f75849b <- 1 c81e728d9d4c2f636f067f89cc14862c <- 2 eccbc87e4b5ce2fe28308fd9f2a7baf3 <- 3 a87ff679a2f3e71d9181a67b7542122c <- 4 e4da3b7fbbce2345d7772b0674a318d5 <- 5 1679091c5a880faf6fb5e6087eb1b2dc <- 6 8f14e45fceea167a5a36dedd4bea2543 <- 7 c9f0f895fb98ab9159f51fd0297e236d <- 8 45c48cce2e2d7fbdea1afc51c7c6ad26 <- 9 d3d9446802a44259755d38e6d163e820 <- 10 # let the program rip over it, suppressing stdout /tmp$ time (./simple_md5 foo.txt > /dev/null) real 0m1.023s user 0m1.008s sys 0m0.012s /tmp$ 

所以这对于30万(短)字符串大约是一秒钟。

 perl -MDigest::MD5=md5_hex -lpe '$_ = md5_hex $_' 
 #~/sw/md5$ time (for i in {0..99}; do md5sum <(echo $i); done) > /dev/null real 0m0.220s user 0m0.084s sys 0m0.160s #~/sw/md5$ time (python test.py `for i in {0..99}; do echo $i; done`) > /dev/null real 0m0.041s user 0m0.024s sys 0m0.012s 

python的代码是这个小样本的五倍,对于较大的样本来说,由于遗漏的原因,差异更大。 1k样本是0.033s到2.3s :)脚本是:

 #!/usr/bin/env python import hashlib, sys for arg in sys.argv[1:]: print hashlib.md5(arg).hexdigest() 

我现在没有机器来测试它,但是md5sum <<< "$i"md5sum <(echo $i)更快吗? <<<语法将避免为echo分派一个子进程的开销,并且会将$i直接传递给标准输入上的md5sum

为了获得更好的性能,您可能需要使用不同的程序,或创建一个调用公共可用md5散列API之一的C程序。

另一种选择是一次产生多个md5调用来利用多个内核。 通过你的每个循环可以产生8个调用,第一个7使用&在结尾(表示异步)。 如果你有4-8个可用内核,可以加速8倍。