Неожиданное поведение с FileInputStream, JAVA - PullRequest
0 голосов
/ 16 июля 2011

Я нахожусь в процессе написания приложения, которое обрабатывает огромное количество целых чисел из двоичного файла (до 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 и, к своему удивлению, получил тот же результат.

У меня естьПонятия не имею, почему это происходит, может кто-нибудь дать мне подсказку?Кроме того, какой будет лучший размер блока в этом случае?

С уважением

Ответы [ 2 ]

1 голос
/ 16 июля 2011

Как уже отмечалось, ваш тест безнадежно скомпрометирован чтением одних и тех же данных для каждого.

Я мог бы извергнуть, но вы, вероятно, получите больше от чтения этой статьи, тогдаглядя на этот пример о том, как использовать FileChannel.

1 голос
/ 16 июля 2011

После того, как вы прочитаете данные в первый раз, они будут в кеше диска.Второе чтение должно быть намного быстрее.Сначала вам нужно запустить тест, который вы считаете более быстрым..

Похоже, что оптимальный размер чтения может быть 32 КБ.Примечание: поскольку файл полностью находится в кеше диска, это может быть не оптимальный размер для файла, который читается с диска.

...