2

Я написал код для тестирования жесткого диска. Это довольно просто: напишите большой кусок байтов (2500 * 10M) на диск с BufferedOutputStream, а затем прочитайте его с помощью BufferedInputStream. Я пишу 2500 байтов каждый раз в течение 10M раз, чтобы имитировать условия в другой программе, которую я написал. Существует также другая глобальная переменная «бессмысленная», которая вычисляется с помощью прочитанных байтов - она ​​абсолютно не имеет смысла и используется только для принудительного выполнения для фактического чтения и использования байтов (чтобы избежать ситуаций, когда байты не читаются из-за некоторой оптимизации).Тест с жестким диском с Java, получение необоснованно быстрых результатов

Код запускается 4 раза и выводит результаты.

Здесь:

import java.io.*; 

public class DriveTest 
{ 
    public static long meaningless = 0; 

    public static String path = "C:\\test"; 

    public static int chunkSize = 2500; 

    public static int iterations = 10000000; 

    public static void main(String[] args) 
    { 
     try 
     { 
      for(int i = 0; i < 4; i++) 
      { 
       System.out.println("Test " + (i + 1) + ":"); 
       System.out.println("=================================="); 

       write(); 
       read(); 

       new File(path).delete(); 

       System.out.println("=================================="); 
      } 
     } 
     catch(Exception e) 
     { 
      e.printStackTrace(); 
     } 
    } 

    private static void write() throws Exception 
    { 
     BufferedOutputStream bos = new BufferedOutputStream(
            new FileOutputStream(new File(path))); 

     long t1 = System.nanoTime(); 

     for(int i = 0; i < iterations; i++) 
     { 
      byte[] data = new byte[chunkSize]; 

      for(int j = 0; j < data.length; j++) 
      { 
       data[j] = (byte)(j % 127); 
      } 

      bos.write(data); 
     } 

     bos.close(); 

     long t2 = System.nanoTime(); 

     double seconds = ((double)(t2 - t1)/1000000000.0); 

     System.out.println("Writing took " + (t2 - t1) + 
          " ns (" + seconds + " seconds)."); 

     System.out.println("Write rate " + (((double)chunkSize * 
          iterations/seconds)/
          (1024.0 * 1024.0)) + " MB/s."); 
    } 

    private static void read() throws Exception 
    { 
     BufferedInputStream bis = new BufferedInputStream(
            new FileInputStream(new File(path))); 

     long t1 = System.nanoTime(); 

     byte[] data; 

     for(int i = 0; i < iterations; i++) 
     { 
      data = new byte[chunkSize]; 

      bis.read(data); 

      meaningless += data[i % chunkSize]; 
     } 

     bis.close(); 

     long t2 = System.nanoTime(); 

     System.out.println("meaningless is: " + meaningless + "."); 

     double seconds = ((double)(t2 - t1)/1000000000.0); 

     System.out.println("Reading Took " + (t2 - t1) + 
          " ns, which is " + 
          seconds + " seconds."); 

     System.out.println("Read rate " + (((double)chunkSize * 
          iterations/seconds)/
          (1024.0 * 1024.0)) + " MB/s."); 
    } 
} 

Проблема здесь двоякая:

  1. При итерации = 10M (запись ~ 23GB на диске), регулярные 7200 RPM привод дает очень быстрые результаты, что выше, чем спецификации:

_

Test 1: 
Writing took 148738975163 ns (148.738975163 seconds). 
Write rate 160.29327810029918 MB/s. 
meaningless is: 1246080000. 
Reading Took 139143051529 ns, which is 139.143051529 seconds. 
Read rate 171.34781541848795 MB/s. 

Test 2: 
Writing took 146591885655 ns (146.591885655 seconds). 
Write rate 162.64104799270686 MB/s. 
meaningless is: 1869120000. 
Reading Took 139845492688 ns, which is 139.845492688 seconds. 
Read rate 170.48713871206587 MB/s. 

Test 3: 
Writing took 152049678671 ns (152.049678671 seconds). 
Write rate 156.8030798785472 MB/s. 
meaningless is: 2492160000. 
Reading Took 140152776858 ns, which is 140.152776858 seconds. 
Read rate 170.11334662539255 MB/s. 

Test 4: 
Writing took 151363950081 ns (151.363950081 seconds). 
Write rate 157.51344951950355 MB/s. 
meaningless is: 3115200000. 
Reading Took 139176911081 ns, which is 139.176911081 seconds. 
Read rate 171.30612919179143 MB/s. 

Это кажется странным - может ли диск достичь таких скоростей? Я серьезно сомневаюсь в том, что, учитывая, что тестируемые спецификации (и даже не по каналам ввода/ввода java, которые, по моему мнению, не должны быть оптимальными!), Ниже: http://hdd.userbenchmark.com/Toshiba-DT01ACA200-2TB/Rating/2736

  1. Когда итерации установлено в 1М (1000000), номера идут с ума:

_

Test 1: 
Writing took 6918084976 ns (6.918084976 seconds). 
Write rate 344.6308912490619 MB/s. 
meaningless is: 62304000. 
Reading Took 2060226375 ns, which is 2.060226375 seconds. 
Read rate 1157.244572706543 MB/s. 

Test 2: 
Writing took 6970893036 ns (6.970893036 seconds). 
Write rate 342.0201369756931 MB/s. 
meaningless is: 124608000. 
Reading Took 2013661185 ns, which is 2.013661185 seconds. 
Read rate 1184.0054368508995 MB/s. 

Test 3: 
Writing took 7140592101 ns (7.140592101 seconds). 
Write rate 333.89188981705496 MB/s. 
meaningless is: 186912000. 
Reading Took 2011346987 ns, which is 2.011346987 seconds. 
Read rate 1185.367719456367 MB/s. 

Test 4: 
Writing took 7140064035 ns (7.140064035 seconds). 
Write rate 333.91658384694375 MB/s. 
meaningless is: 249216000. 
Reading Took 2041787713 ns, which is 2.041787713 seconds. 
Read rate 1167.6952387535623 MB/s. 

Какие кэширования колдовство это ?? (что такое кеширование может привести к тому, что пишет: будет быстрее?) :) И как его можно отменить? Я прочитал и написал файлы объемом 2,3 ГБ! это какое-то огромное кэширование, если это действительно проблема.

Благодаря

+0

Ваши последовательные скорости записи выглядят разумно. У меня есть внешний жесткий диск 5900 об/мин, который обычно имеет производительность около 120 МБ/с. – chrylis

+0

Вы проверили кеш системы FS? Я предполагаю, что ваша система имеет между> 2,3 и <23 ГБ памяти, поэтому файл с 23 ГБ не подходит, но файл с 2,3 ГБ. Система может хранить весь файл в кеше FS, и, следовательно, второй тест выходит за рамки. –

+0

16GB :), но кэширование не объясняет результаты записи, правильно? – amirkr

ответ

3

Ваш тест, вероятно, только чтение и запись в кэше страниц OS. Небольшой размер данных будет полностью вписываться. Более крупный не будет, но будет асинхронно сбрасываться ОС. Вы должны попробовать использовать опции OpenOptions.DSYNC и SYNC.

+0

Большое спасибо. Кажется, это проблема кэширования (а асинхронная запись может объяснить ускорение). Я контролирую использование RAM, и действительно, он достигает значения «изменено» примерно на 1.5 ГБ с каждой итерацией программы, затем снова падает. Как я могу использовать перечисление StandardOpenOptions с буферизованным потоком? где я его помещаю, или где ставить его статически? – amirkr

+0

@amirkr: 'write()' системные вызовы могут и возвращаться, как только данные находятся в кеше страницы. Они не дожидаются, пока данные попадут на диск, потому что есть веские причины не инициировать запись на диск сразу. (например, возможно, это файл tmp, который вот-вот будет удален, и в этом случае это нормально, если его данные никогда не попадут на диск вообще.) –

+0

@PeterCordes, но не будет ли запись в этом случае быстро вспыхивать? Если данные просто находятся в кеше, который находится в супер быстрой основной памяти, запись заканчивается как часть секунды. Так много переменных здесь (буферизация, кеширование, ограничения ОС, кэш жесткого диска, пропускная способность жесткого диска, буферы java-объектов ... почти невозможно оценить скорость :)) – amirkr