Я унаследовал фрагмент кода, который интенсивно использует преобразования String -> byte [] и наоборот для некоторого собственного кода сериализации. По сути, объекты Java знают, как преобразовать свои составные части в строки, которые затем преобразуются в байт []. Указанный байтовый массив затем передается через JNI в код C ++, который восстанавливает byte [] в C ++ std :: strings и использует их для начальной загрузки объектов C ++, которые отражают объекты Java. Это немного больше, но это высокоуровневое представление о том, как работает этот фрагмент кода; Связь работает так в обоих направлениях, так что переход C ++ -> Java является зеркальным отражением перехода Java -> C ++, о котором я упоминал выше.
Одна часть этого кода - фактическое преобразование строки в байт [] - неожиданно обнаруживается в профилировщике как нагружающий много ЦП. Конечно, передается много данных, но это неожиданное узкое место.
Основная схема кода выглядит следующим образом:
public void convertToByteArray(String convert_me, ByteArrayOutputStream stream)
{
stream.write(convert_me.getBytes());
}
Функция немного больше, но не намного. Вышеупомянутая функция вызывается один раз для каждого объекта String / Stringified, и после того, как все составляющие записаны в ByteArrayOutputStream, ByteArrayOutputStream преобразуется в byte []. Если разбить вышесказанное на более удобную для профилировщика версию путем извлечения вызова convert_me.getBytes()
, то видно, что более 90% времени в этой функции тратится на вызов getBytes ().
Есть ли способ улучшить производительность вызова getBytes () или есть другой, потенциально более быстрый способ добиться того же преобразования?
Количество конвертируемых объектов довольно велико. На прогонах профилирования, которые используют только небольшое подмножество производственных данных, я вижу что-то вроде 10 миллионов плюс обращений к вышеуказанной функции преобразования.
В связи с тем, что мы очень близки к тому, чтобы выпустить проект в производство, есть несколько обходных путей, которые на данный момент невозможны:
- Перепишите интерфейс сериализации, чтобы просто передавать объекты String через уровень JNI. Это очевидный (для меня) способ улучшения ситуации, но он потребует серьезного реинжиниринга уровня сериализации. Учитывая тот факт, что мы собираемся в UAT в начале этой недели, уже слишком поздно для такого рода сложных изменений. Это моя главная задача для следующего релиза, так что это будет сделано; Однако до тех пор мне нужен обходной путь, но пока код работает, используется годами и имеет большую часть изломков. Ну, кроме спектакля.
- Изменение JVM (в настоящее время 1.5) также не вариант. К сожалению, это JVM по умолчанию, которая установлена на клиентских компьютерах, и обновление до версии 1.6 (которая может или не может быть быстрее в этом случае), к сожалению, невозможно. Любой, кто работал в крупных организациях, вероятно, понимает, почему ...
- В дополнение к этому, мы уже сталкиваемся с ограничениями памяти, поэтому попытка кэшировать хотя бы более крупные строки и представление их байтового массива, будучи потенциально элегантным решением, может вызвать больше проблем, чем решит