简短的问题:
为什么在Raspberry Pi上计算Java中5 MB文件的md5-sum需要84秒,而Mac只需要25 ms?
整个问题:
我需要编写一个Java程序,它计算一堆文件的md5或sha-sum,这些文件的大小总共约为50 GB。
为此我编写了一个简单的Java程序,它计算单个5 MB文件的校验和。这是Java程序:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
public class Main {
public static final int BLOCKSIZE = 8*1024;
public static void main(String[] args) throws FileNotFoundException, NoSuchAlgorithmException{
String path = Main.class.getResource("file5M.img").getPath();
File file = new File(path);
FileInputStream fin = new FileInputStream(file);
MessageDigest messageDigest = MessageDigest.getInstance("MD5");
long fileSize = file.length();
int length;
long alreadyRead = 0;
long startTime = System.currentTimeMillis();
byte[] bytes = new byte[BLOCKSIZE];
try {
while (true) {
int maxToRead = (int) (fileSize - alreadyRead < BLOCKSIZE ? fileSize - alreadyRead : BLOCKSIZE);
if ((length = fin.read(bytes, 0, maxToRead)) < 0) break;
messageDigest.update(bytes, 0, length);
if ((alreadyRead += length) >= fileSize) break;
}
} catch (IOException ex){
ex.printStackTrace();
}
byte[] md5 = messageDigest.digest();
long stopTime = System.currentTimeMillis();
long elapsedTime = stopTime - startTime;
System.out.println("Time:\t" + elapsedTime + "\tRead:\t" + alreadyRead/1024/1024);
System.out.println("MD5: " + Arrays.toString(md5));
}
}
为了创建随机文件图像,我使用了这个Linux命令:
dd if=/dev/urandom of=file5M.txt bs=1M count=5
在不同的设备上执行程序会导致令人困惑的结果:
<table style="width:100%">
<tr>
<th>Time in ms</th>
<th>Computer</th>
<th>CPU</th>
<th>RAM</th>
<th>Harddrive</th>
<th>Operating-System</th>
</tr>
<tr>
<td>24</td>
<td>MacBook Pro (13-inch, 2016)</td>
<td>3.3 GHz Intel Core i7</td>
<td>8 GB 2133 MHz LPDDR3</td>
<td>APPLE SSD AP1024J</td>
<td>MacOs Sierra</td>
</tr>
<tr>
<td>45000</td>
<td>Raspberry Pi Modell B</td>
<td>0.7 GHz ARMv6 (32-bit)</td>
<td>256 MB</td>
<td>PRO microSD Card (SD Adapter)</td>
<td>Arch Linux</td>
</tr>
<tr>
<td>7600</td>
<td>Odroid XU4</td>
<td>Exynos5 Octa Cortex™-A15 1.6Ghz quad core and Cortex™-A7 quad core CPUs</td>
<td>2Gbyte LPDDR3 RAM PoP</td>
<td>Samsung PRO microSD Card (SD Adapter)</td>
<td>Arch Linux for Odroid-XU3</td>
</tr>
<tr>
<td>300</td>
<td>VirtualBox on MacBook Pro</td>
<td>1 Core with 0.7GHz (21% of MacCPU) no PAE/NX, no acceleration</td>
<td>256MB of MacRAM PIIX3 with APIC</td>
<td>Dynamic Allocated 8GB (VDI)</td>
<td>Arch Linux 64-Bit</td>
</tr>
</table>
那么为什么在MacBook上执行程序的速度要快得多,即使我限制了VirtualBox中的CPU和RAM?
瓶颈在哪里?
我需要做些什么才能在Odroid-XU4上大约300毫秒内执行程序?
说明:
我不认为它是microSD的I / O,因为它在不计算md5sum的情况下非常快速地读取整个文件。
在odroid上将cpu频率从2Ghz更改为500MHz,计算时间从7秒增加到24秒。
答案 0 :(得分:1)
Raspberry Pi的RAM频率比MacBook低得多。它可能就是为什么它甚至在VirtualBox中运行得更快。因为当您读取文件时,它将存储在RAM中,即使速度非常快,每次读取文件时都可以进行I / O访问,并将其与MD5算法相加。
此外,如果你想提高性能,我建议你在你的程序中使用线程(在线程之间调度文件)。请注意,如果您的VM上只有一个核心,则线程无用。