Я нахожусь в процессе написания приложения, которое обрабатывает огромное количество целых чисел из двоичного файла (до 50 мегабайт).Мне нужно сделать это как можно быстрее, и основной проблемой производительности является время доступа к диску, так как я делаю большое количество операций чтения с диска, оптимизация времени чтения повысила бы производительность приложения в целом.
До сих пор я думал, что чем меньше блоков, на которые я разбил свой файл (то есть, чем меньше у меня операций чтения / чем больше размер чтения), тем быстрее должно работать мое приложение.Это связано с тем, что поиск жесткого диска происходит очень медленно, т. Е. Определяется начало блока из-за его механической природы.Однако, как только он обнаружит начало блока, который вы попросили прочитать, он должен выполнить реальное чтение довольно быстро.
Ну, это было до тех пор, пока я не запустил этот тест:
Старый тест удален, возникли проблемы из-за кэширования жесткого диска
NEW TEST (кэш жесткого диска здесь не помогает, так как файл слишком большой (1 ГБ) и я обращаюсь к случайным местам внутри него):
int mega = 1024 * 1024;
int giga = 1024 * 1024 * 1024;
byte[] bigBlock = new byte[mega];
int hundredKilo = mega / 10;
byte[][] smallBlocks = new byte[10][hundredKilo];
String location = "C:\\Users\\Vladimir\\Downloads\\boom.avi";
RandomAccessFile raf;
FileInputStream f;
long start;
long end;
int position;
java.util.Random rand = new java.util.Random();
int bigBufferTotalReadTime = 0;
int smallBufferTotalReadTime = 0;
for (int j = 0; j < 100; j++)
{
position = rand.nextInt(giga);
raf = new RandomAccessFile(location, "r");
raf.seek((long) position);
f = new FileInputStream(raf.getFD());
start = System.currentTimeMillis();
f.read(bigBlock);
end = System.currentTimeMillis();
bigBufferTotalReadTime += end - start;
f.close();
}
for (int j = 0; j < 100; j++)
{
position = rand.nextInt(giga);
raf = new RandomAccessFile(location, "r");
raf.seek((long) position);
f = new FileInputStream(raf.getFD());
start = System.currentTimeMillis();
for (int i = 0; i < 10; i++)
{
f.read(smallBlocks[i]);
}
end = System.currentTimeMillis();
smallBufferTotalReadTime += end - start;
f.close();
}
System.out.println("Average performance of small buffer: " + (smallBufferTotalReadTime / 100));
System.out.println("Average performance of big buffer: " + (bigBufferTotalReadTime / 100));
РЕЗУЛЬТАТЫ: Среднее для маленького буфера - 35 мс Среднее для большого буфера - 40 мс ?!(Пробовал на Linux и Windows, в обоих случаях больший размер блока приводит к увеличению времени чтения, почему?)
После многократного выполнения этого теста я понял, что по какой-то магической причине чтение одного большого блока занимаетв среднем дольше, чем чтение 10 блоков меньшего размера последовательно.Я подумал, что это могло быть результатом того, что Windows слишком умна и пытается что-то оптимизировать в своей файловой системе, поэтому я запустил тот же код в Linux и, к своему удивлению, получил тот же результат.
У меня естьПонятия не имею, почему это происходит, может кто-нибудь дать мне подсказку?Кроме того, какой будет лучший размер блока в этом случае?
С уважением