Java 从磁盘获取不同的文件读取速度
我正在开发一个Java应用程序,从磁盘读取多个文本文件,修改它们并将修改后的文件写回磁盘。当我从中使用“FileReadTestJavaGui-1.05.jar”运行读取测试时,读取速度高达250 MB/秒。当我运行下面给出的测试应用程序时,读取速度低至11.75 MB/秒。我正在使用ThreadPoolExecutor,无法获得一致的读/写速度。任何解决此问题的建议都是非常受欢迎的。我在Windows 2008 Server R2机器上运行了这些测试,该机器是Dell双四核2.4 GHz机器,内存为12 GBJava 从磁盘获取不同的文件读取速度,java,threadpoolexecutor,Java,Threadpoolexecutor,我正在开发一个Java应用程序,从磁盘读取多个文本文件,修改它们并将修改后的文件写回磁盘。当我从中使用“FileReadTestJavaGui-1.05.jar”运行读取测试时,读取速度高达250 MB/秒。当我运行下面给出的测试应用程序时,读取速度低至11.75 MB/秒。我正在使用ThreadPoolExecutor,无法获得一致的读/写速度。任何解决此问题的建议都是非常受欢迎的。我在Windows 2008 Server R2机器上运行了这些测试,该机器是Dell双四核2.4 GHz机器,
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class RunTest {
private static String baseFileName = "C:/logs/input_";
private static class FileReaderRunnable implements Runnable {
public FileReaderRunnable(int threadID) {
super();
this.threadID = threadID;
}
int threadID = -1;
@Override
public void run() {
Thread.currentThread().setName("Thread-" + threadID);
String writeBaseFileName = "c:/temp/output";
String[] args = {baseFileName + threadID + ".log", writeBaseFileName + threadID + ".txt"};
readAndWriteFileInputOutputStream(args);
}
}
public static void main(String[] args) {
int MAX_THREADS = 20;
int coreThreadPoolSize = 2;
int maxThreadPoolSize = 4;
long threadKeepAliveTime = 12000000;
int arrayBlockQueueSize = 400;
ThreadPoolExecutor executor = new ThreadPoolExecutor(
coreThreadPoolSize,
maxThreadPoolSize,
threadKeepAliveTime,
TimeUnit.MILLISECONDS,
new ArrayBlockingQueue<Runnable>(arrayBlockQueueSize, true));
for (int i = 0; i < MAX_THREADS; i++) {
FileReaderRunnable frr = new FileReaderRunnable(i+1);
executor.execute(frr);
}
executor.shutdown();
while (!executor.isTerminated()) {
try {
Thread.sleep(5000);
print("********** executor.getPoolSize()=" + executor.getPoolSize());
print("********** executor.getCorePoolSize()=" + executor.getCorePoolSize());
print("********** executor.getActiveCount()=" + executor.getActiveCount());
print("********** executor.getCompletedTaskCount()=" + executor.getCompletedTaskCount());
print("********** executor.getTaskCount()=" + executor.getTaskCount());
print("********** executor.isShutdown()=" + executor.isShutdown());
print("********** executor.isTerminated()=" + executor.isTerminated());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void readAndWriteFileInputOutputStream(String[] args) {
try {
String routineName = Thread.currentThread().getName();
String fInp = "c:\\temp\\input.txt";
String fOut = "c:\\temp\\output.txt";
if( args.length > 0 ) {
fInp = args[0];
}
if( args.length > 1 ) {
fOut = args[1];
}
FileInputStream fis = null;
FileOutputStream fos = null;
// delete the file if it exists
File fff = new File( fOut );
if( fff.exists() ) {
fff.delete();
}
fff = null;
fos = new FileOutputStream(fOut);
fis = new FileInputStream( fInp );
long readTime = 0;
long writeTime = 0;
final int FILE_CHUNK_SIZE = 16 * 1024;
byte[] buffer = new byte[ FILE_CHUNK_SIZE ];
long sTOverall = System.nanoTime();
final long fileLen = fis.available();
for ( long restSize = fileLen; restSize > 0; ) {
final int sizeToProcess = (int) java.lang.Math.min( restSize, FILE_CHUNK_SIZE );
long sT = System.nanoTime();
final int actuallyRead = fis.read( buffer, 0, sizeToProcess );
readTime += System.nanoTime() - sT;
restSize -= actuallyRead;
long sT0 = System.nanoTime();
fos.write(buffer);
writeTime += System.nanoTime() - sT0;
}
sTOverall = System.nanoTime() - sTOverall;
fff = new File(fOut);
double size = ((double)fff.length()) / (1024 * 1024);
double secTaken = ((double)writeTime) / 1000000000;
print(routineName + ": Took: " + secTaken + " sec to write " + size + " MB which is " + (size/secTaken) + " MB/sec");
fos.close();
File fff2 = new File(fInp);
size = ((double)fff2.length()) / (1024 * 1024);
secTaken = ((double)readTime) / 1000000000;
print(routineName + ": Took: " + secTaken + " sec to read " + size + " MB which is " + (size/secTaken) + " MB/sec");
fis.close();
print(routineName + ": Took " + sTOverall + " nanosec overall");
} catch (IOException e) {
e.printStackTrace();
}
}
public static void print(String string) {
System.out.println(string);
}
}
您的写入时间在所有跑步中都是一致的。您的读取时间开始时非常快(>1 GB/s),但最终会见底。我怀疑发生的情况是您已经超过了系统的磁盘缓存容量。对于前10个线程,您正在写入的数据卡在系统的磁盘缓存中,因此读取速度非常快。在第10个线程之后,您已经写入了足够的数据,系统开始丢弃缓存的数据,实际上必须转到磁盘读取数据。它应该一直保持MRU模块,但也许不是。您没有指定什么操作系统,因此甚至无法推测发生了什么 这是一个警示性的故事,微基准点充满了危险。在现代操作系统上,有很多优化在你后面进行,比如JIT编译、磁盘缓存(在OS中、磁盘控制器和磁盘本身)等等,并且在基准测试时,你必须考虑这些因素,尤其是java操作执行速度和I/O 等基本操作。 我怀疑FileReadTestJavaGui没有写入足够的数据来遇到同样的问题
底线是,如果不深入了解代码和“裸机”之间发生的一切,您就无法获得一致的结果,甚至无法确切地知道您正在测量的是什么。我怀疑您没有使用直接I/O来避免在RAM中缓存数据(在Java中可能吗?)。如果您使用的是Linux,您可能希望运行vmstat来查看发生了什么,或者在Windows中运行Perfmon。我目前正在写关于Raspberry Pi的基准测试和压力程序。下面是磁盘(SD卡)测试的vmstat结果,首先是直接I/O,其中文件缓存保持较小,CPU利用率较低。第二种是缓存I/O,其中缓存可以包含所用文件的所有数据,并且以100%的CPU利用率从RAM读取数据。RPi只有512MB相对较慢的RAM。使用4 x 164 MB文件的进一步测试不会缓存这些文件以供读取,但当操作系统意识到文件正在被重新读取时,重复运行可能会有一些缓存。无论文件大小如何,缓存速度都会有很大差异
vmstat 15 25 > vmstats44.txt
15 second periods, 25 samples
Write 4 files of 82 MB in 46 seconds = 7.1 MB/sec bo
Read 3 x 4 x 82 MB in 62 second = 15.8 MB/sec bi
Reread 49200 x 64 KB in 167 seconds = 18.4 MB/sec bi
Rereads 64 KB block for 1 second from
164 blocks in one file
procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----
r b swpd free buff cache si so bi bo in cs us sy id wa
1 0 0 349476 2772 33484 0 0 51 439 1264 229 15 30 53 2
0 1 0 347428 2796 33532 0 0 2 6996 3793 914 17 42 0 41
1 1 0 347172 2904 33592 0 0 6 6851 3736 849 11 41 0 48
1 1 0 347172 2932 33616 0 0 1 7536 3996 931 11 46 0 43
2 0 0 347048 2948 33616 0 0 13965 1053 6187 1264 14 18 0 68
0 1 0 347048 2964 33616 0 0 16188 3 6524 1314 13 14 0 73
1 0 0 347048 2972 33616 0 0 16427 3 6605 1333 12 14 0 74
0 1 0 347048 2980 33616 0 0 16439 2 6607 1335 13 14 0 73
2 0 0 347048 2996 33616 0 0 18253 3 7198 1471 7 9 0 84
1 1 0 347048 3020 33616 0 0 18842 5 7393 1510 4 10 0 87
0 1 0 346924 3044 33616 0 0 18833 6 7389 1512 2 10 0 88
0 1 0 346924 3068 33616 0 0 18842 5 7393 1504 4 10 0 87
1 0 0 346924 3092 33616 0 0 18859 6 7398 1509 3 8 0 89
0 1 0 346924 3116 33616 0 0 18854 5 7390 1509 3 9 0 88
0 1 0 346800 3140 33616 0 0 18859 5 7395 1508 4 9 0 87
1 1 0 346800 3164 33616 0 0 18820 6 7385 1501 3 10 0 87
1 1 0 346800 3188 33616 0 0 18842 5 7391 1506 3 8 0 89
1 1 0 346800 3212 33616 0 0 18829 5 7386 1507 3 9 0 88
0 1 0 346676 3236 33616 0 0 18816 6 7384 1495 4 9 0 88
0 0 0 346800 3252 33552 0 0 7428 7 3632 640 4 4 59 32
Cached test - see cache size details
Write 4 x 82 MB time 2.3, 9.1, 12.3, 2.4 seconds average 12.6 MB/sec bo
Read 19 x 4 x 82 MB in 63 seconds = 99 MB/sec cpu us sy
Reread 1158120 x 64 KB in 164 seconds = 441 MB/sec cpu us sy
procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----
r b swpd free buff cache si so bi bo in cs us sy id wa
2 0 0 355484 3692 29308 0 0 60 345 1260 204 14 26 58 2
0 3 0 124856 3976 254388 0 0 27 13562 1661 1889 16 34 0 50
1 1 0 11476 4000 365356 0 0 0 8850 1413 2556 10 23 0 67
1 0 0 11476 4012 365420 0 0 0 2 1750 1118 48 52 0 0
1 0 0 11344 4020 365420 0 0 0 2 1270 122 50 50 0 0
1 0 0 11352 4028 365420 0 0 0 4 1271 61 46 54 0 0
1 1 0 11600 3616 365572 0 0 57 2 1292 77 44 56 0 0
1 0 0 12320 1940 366340 0 0 254 6 1376 111 14 86 0 0
1 0 0 11476 1964 367540 0 0 80 4 1304 91 14 86 0 0
1 0 0 11352 1988 367540 0 0 0 5 1277 82 12 88 0 0
1 0 0 11352 2012 367540 0 0 0 5 1275 79 13 87 0 0
1 0 0 11228 2036 367540 0 0 0 5 1276 85 14 86 0 0
2 0 0 11228 2060 367540 0 0 0 4 1276 80 13 87 0 0
2 0 0 11228 2084 367540 0 0 0 5 1276 77 13 87 0 0
1 0 0 11228 2108 367540 0 0 0 4 1276 83 13 87 0 0
1 0 0 11104 2132 367540 0 0 0 4 1276 78 12 88 0 0
1 0 0 10980 2300 367552 0 0 9 9 1282 80 11 89 0 0
0 0 0 352104 2324 31696 0 0 1 5 1273 90 12 81 7 0
您是否检查了FileReadTestJavaGui的源代码,以了解它们的代码与您的代码有何不同?另外,还不清楚您在这里要问什么,因为您的一些线程的速度似乎在1 GB/s范围内。我正在使用FileReadTestGui中的FileInputBuffer。我的问题是,我该怎么做才能使所有线程的读取速度保持一致。目前,这些线程中只有少数线程具有较高的读取速度,而其余线程的读取速度非常低。很抱歉,我忘了提及我在Windows 2008 Server R2机器上运行了这些测试,该机器是Dell双四核2.4 GHz机器,内存为12 GB。
vmstat 15 25 > vmstats44.txt
15 second periods, 25 samples
Write 4 files of 82 MB in 46 seconds = 7.1 MB/sec bo
Read 3 x 4 x 82 MB in 62 second = 15.8 MB/sec bi
Reread 49200 x 64 KB in 167 seconds = 18.4 MB/sec bi
Rereads 64 KB block for 1 second from
164 blocks in one file
procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----
r b swpd free buff cache si so bi bo in cs us sy id wa
1 0 0 349476 2772 33484 0 0 51 439 1264 229 15 30 53 2
0 1 0 347428 2796 33532 0 0 2 6996 3793 914 17 42 0 41
1 1 0 347172 2904 33592 0 0 6 6851 3736 849 11 41 0 48
1 1 0 347172 2932 33616 0 0 1 7536 3996 931 11 46 0 43
2 0 0 347048 2948 33616 0 0 13965 1053 6187 1264 14 18 0 68
0 1 0 347048 2964 33616 0 0 16188 3 6524 1314 13 14 0 73
1 0 0 347048 2972 33616 0 0 16427 3 6605 1333 12 14 0 74
0 1 0 347048 2980 33616 0 0 16439 2 6607 1335 13 14 0 73
2 0 0 347048 2996 33616 0 0 18253 3 7198 1471 7 9 0 84
1 1 0 347048 3020 33616 0 0 18842 5 7393 1510 4 10 0 87
0 1 0 346924 3044 33616 0 0 18833 6 7389 1512 2 10 0 88
0 1 0 346924 3068 33616 0 0 18842 5 7393 1504 4 10 0 87
1 0 0 346924 3092 33616 0 0 18859 6 7398 1509 3 8 0 89
0 1 0 346924 3116 33616 0 0 18854 5 7390 1509 3 9 0 88
0 1 0 346800 3140 33616 0 0 18859 5 7395 1508 4 9 0 87
1 1 0 346800 3164 33616 0 0 18820 6 7385 1501 3 10 0 87
1 1 0 346800 3188 33616 0 0 18842 5 7391 1506 3 8 0 89
1 1 0 346800 3212 33616 0 0 18829 5 7386 1507 3 9 0 88
0 1 0 346676 3236 33616 0 0 18816 6 7384 1495 4 9 0 88
0 0 0 346800 3252 33552 0 0 7428 7 3632 640 4 4 59 32
Cached test - see cache size details
Write 4 x 82 MB time 2.3, 9.1, 12.3, 2.4 seconds average 12.6 MB/sec bo
Read 19 x 4 x 82 MB in 63 seconds = 99 MB/sec cpu us sy
Reread 1158120 x 64 KB in 164 seconds = 441 MB/sec cpu us sy
procs -----------memory---------- ---swap-- -----io---- -system-- ----cpu----
r b swpd free buff cache si so bi bo in cs us sy id wa
2 0 0 355484 3692 29308 0 0 60 345 1260 204 14 26 58 2
0 3 0 124856 3976 254388 0 0 27 13562 1661 1889 16 34 0 50
1 1 0 11476 4000 365356 0 0 0 8850 1413 2556 10 23 0 67
1 0 0 11476 4012 365420 0 0 0 2 1750 1118 48 52 0 0
1 0 0 11344 4020 365420 0 0 0 2 1270 122 50 50 0 0
1 0 0 11352 4028 365420 0 0 0 4 1271 61 46 54 0 0
1 1 0 11600 3616 365572 0 0 57 2 1292 77 44 56 0 0
1 0 0 12320 1940 366340 0 0 254 6 1376 111 14 86 0 0
1 0 0 11476 1964 367540 0 0 80 4 1304 91 14 86 0 0
1 0 0 11352 1988 367540 0 0 0 5 1277 82 12 88 0 0
1 0 0 11352 2012 367540 0 0 0 5 1275 79 13 87 0 0
1 0 0 11228 2036 367540 0 0 0 5 1276 85 14 86 0 0
2 0 0 11228 2060 367540 0 0 0 4 1276 80 13 87 0 0
2 0 0 11228 2084 367540 0 0 0 5 1276 77 13 87 0 0
1 0 0 11228 2108 367540 0 0 0 4 1276 83 13 87 0 0
1 0 0 11104 2132 367540 0 0 0 4 1276 78 12 88 0 0
1 0 0 10980 2300 367552 0 0 9 9 1282 80 11 89 0 0
0 0 0 352104 2324 31696 0 0 1 5 1273 90 12 81 7 0