У меня есть веб-приложение, в котором пользователи загружают изображения. Мы проверяем данные изображения с помощью ImageIO.read() и выполняем несколько простых преобразований полученного BufferedImage перед его сохранением на диск.
Выполняя нагрузочное тестирование, мы поняли, что когда одновременно поступает много запросов, они блокируются в вызове ImageIO.read(). Копнув глубже, мы заметили, что JPEGImageReader синхронизирован и одновременно создается только одно BufferedImage.
Кто-нибудь еще сталкивался с этим? Я гуглил это в течение нескольких дней и не встречал другого человека, у которого была эта проблема, так что, возможно, я делаю что-то не так. Я не могу придумать никакой логической причины, почему это могло бы быть. Кажется, это связано с невозможностью создания отдельных модулей чтения и записи для каждого образа из-за какой-то проблемы с утечкой памяти, но это объяснение кажется мне довольно тонким.
РЕДАКТИРОВАТЬ: Вот инструмент производительности, который разбивает то, что занимает так много времени. Я считаю, что это связано с тем, что все потоки ожидают блокировки синхронизации, JPEGImageReader источник.
РЕДАКТИРОВАТЬ: Библиотеки JAI работали бы, за исключением того, что OpenJDK удалил поддержку его критических частей, явно кодека JPEG.
РЕШЕНИЕ. Учитывая количество времени, которое я потратил, пытаясь найти альтернативное решение и не найдя его, моим лучшим решением была асинхронная обработка изображений по отношению к запросам. Итак, когда приходит запрос, необработанные данные изображения сохраняются как предположительно допустимое изображение; затем асинхронный процесс вне потоков запросов будет обрабатывать каждое изображение по одному. Из-за синхронности библиотеки ImageIO нет никакой выгоды от попытки сделать несколько одновременно. Изображения могут обрабатываться параллельно, учитывая, что библиотека не является синхронной, а только неэффективной.
Хотя выполнение асинхронной обработки добавляет уровень сложности, это, вероятно, хорошая идея в отношении изменения изображения. Что не работает, так это то, что мы не можем обрабатывать исходное изображение в каждом запросе, а это означает, что наша система должна делать предположение, что каждое изображение является допустимыми данными изображения. Когда асинхронный процессор обрабатывает изображение, могут возникнуть несоответствия в системе, если данные неверны.
JPEGImageReader
сериализуются в классе (т.е. однопоточные)? Как вы определили, что это так? Если да, то где монитор, на котором они все блокируются/ожидают? - person Jim Garrison   schedule 30.07.2013