Прямой доступ к объекту = в 94 117 раз быстрее, чем чтение из файла?

Я написал небольшой класс, который в основном извлекает данные из файла CSV и загружает их в объект POJO. Поскольку мне нужен частый доступ к этим данным, я написал одноэлементный класс, который проверяет, есть ли данные уже в объекте, и если да, он просто возвращает данные непосредственно из объекта (без необходимости снова получать их из файла). В противном случае он извлекает данные из файла и сохраняет данные в объекте для будущих запросов.

При тестировании я заметил, что для доступа к данным 10 000 раз требуется примерно 175 миллисекунд (включая первую загрузку данных из файла).

Что меня поразило, так это то, что когда я зацикливал 20000 раз, это заняло всего 177 миллисекунд (всего две миллисекунды больше, чем 10000 раз), а 50 000 раз заняло всего около 197 миллисекунд.

Какое объяснение тому, что намного быстрее сделать 50K по сравнению с 10K? Почему время не увеличивается пропорционально?

Также почему доступ к данным напрямую из объекта происходит намного быстрее, чем доступ к нему с диска (когда я обращаюсь к нему через файл, это занимает около 160 миллисекунд за один раз)

Спасибо

Обновление:

Возможно, еще больше озадачивает то, что когда я пытаюсь получить доступ к объекту с помощью двух разных ключей (что требует двух операций чтения из файла), это занимает примерно такое же количество времени (с вариацией в 1 миллисекунду), чем однократный доступ к нему. Все объяснения того, что доступ к объектам в 200 тысяч раз быстрее, чем доступ к файлам, объясняет только мое первое наблюдение, но теперь я фактически читаю данные из двух разных файлов, но не вижу пропорционального увеличения количества времени, которое требуется.

Другими словами, делаем это:

    for (int counter = 0; counter < 1; counter++) {

        POJOObj.getInstance().getKey("Key1", "Val1");

    }

занимает столько же времени, как и это:

for (int counter = 0; counter < 1; counter++) {

        POJOObj.getInstance().getKey("Key1", "Val1");
        POJOObj.getInstance().getKey("Key1", "Val2"); // this requires new read from file

    }

Почему время не увеличивается пропорционально?


person S.O.S    schedule 29.08.2018    source источник
comment
Для доступа из файла требуется дисковый ввод-вывод. Доступ из объекта осуществляется прямо из памяти. См .: stackoverflow.com/questions/1371400/ Вам также следует ознакомиться с основами работы кеширования, которые объясняют, почему оно не увеличивается пропорционально, как вы говорите.   -  person noahnu    schedule 29.08.2018
comment
Почему время не увеличивается пропорционально? Скорее всего, потому, что ваша логика тестирования производительности некорректна. См. Как мне написать правильный микротест на Java?   -  person Andreas    schedule 29.08.2018


Ответы (1)


Чтение файла с диска происходит намного медленнее, чем чтение данных из памяти. Существует довольно хороший ресурс под названием «Числа задержки, который должен знать каждый разработчик», который частично объясняет это . По сути, чтение 1 МБ с диска примерно в 200 000 раз медленнее, чем чтение того же объема из основной памяти.

Что касается того, почему вы видите более быстрое время отклика от вашего метода - вероятно, сработала Hotspot (внутренний компилятор JVM). Когда вы часто выполняете метод на Java, JVM обнаружит это после некоторого порога (я хочу сказать, что это около 10 тыс. Вызовов , но не верьте мне в этом) и оптимизируйте метод. Он делает это путем преобразования интерпретированного байт-кода, который вы выполняли, во встроенную сборку. Это намного быстрее и происходит за кулисами. Написание микробенчмарков, таких как у вас, исключительно сложно, и есть много способов испортить это. Ознакомьтесь с этим ресурсом Oracle о некоторых из подводные камни и как их избежать с помощью инструмента под названием JMH, если вы заинтересованы в дальнейшем изучении этих чисел.

person Todd    schedule 29.08.2018
comment
чтение 1 МБ с диска примерно в 200 000 раз медленнее, чем чтение того же самого из основной памяти И это идеально, вероятно, для чего-то вроде быстрого SSD. Достаточно сильно испортите свой ввод-вывод на медленном диске SATA, который может выполнять только 40 или 50 поисков головок в секунду, а чтение МБ может занять до 30 или 40 секунд. - person Andrew Henle; 29.08.2018