Быстрая альтернатива java.nio.charset.Charset.decode (..) / encode (..) - PullRequest
4 голосов
/ 20 января 2010

Кто-нибудь знает более быстрый способ сделать то, что делает java.nio.charset.Charset.decode(..) / encode(..)?

В настоящее время это одно из узких мест технологии, которую я использую.

[ПРАВИТЬ]В частности, в моем приложении я изменил один сегмент с java-решения на JNI-решение (потому что была технология C ++, которая больше всего подходила для моих нужд, чем используемая мной технология Java).

Это изменение привело к значительному снижению скорости (и значительному увеличению использования процессора и памяти).

Глубже изучая JNI-решение, которое я использовал, java-приложение связывается с приложением C ++ через byte [].Эти byte [] создаются Charset.encode (..) со стороны java и передаются на сторону C ++.Затем, когда ответ C ++ с байтом [], он декодируется на стороне java через Charset.decode (..).

Запустив это с профилировщиком, я вижу, что Charset.decode (..) иCharset.encode (..) оба заняли значительно более длительное время по сравнению со всем временем выполнения JNI-решения (я профилировал только JNI-решение, потому что это то, что я мог бы быстро вспомнить. Я профилирую все приложение напозднее свидание, как только я освобожу свой график :-)).

После прочтения о моей проблеме кажется, что это известная проблема с Charset.encode (..) и декодированием (..), и она решается в Java7.Тем не менее, переход на Java7 не является для меня вариантом (на данный момент) из-за некоторых ограничений.

Именно поэтому я спрашиваю здесь, знает ли кто-нибудь решение / альтернативу Java5 (извините, я должен был упомянуть, что это было для Java5 раньше)?: -)

Ответы [ 3 ]

6 голосов
/ 20 января 2010

Javadoc для encode() и decode() дает понять, что это удобные методы.Например, для encode () :

Удобный метод, который кодирует символы Unicode в байты в этой кодировке.

Вызов этого метода для кодировки csвозвращает тот же результат, что и выражение

 cs.newEncoder()
   .onMalformedInput(CodingErrorAction.REPLACE)
   .onUnmappableCharacter(CodingErrorAction.REPLACE)
   .encode(bb); 

, за исключением того, что он потенциально более эффективен, поскольку может кэшировать кодировщики между последовательными вызовами.

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

 CharsetEncoder encoder = cs.newEncoder()
   .onMalformedInput(CodingErrorAction.REPLACE)
   .onUnmappableCharacter(CodingErrorAction.REPLACE);

 encoder.encode(...);
 encoder.encode(...);
 encoder.encode(...);
 encoder.encode(...);

Всегда полезно читать Javadoc, даже если вы думаете, что уже знаете ответ.

2 голосов
/ 09 января 2013

Первая часть - вообще плохая идея передавать массивы в код JNI.Из-за GC Java должна копировать массивы.В данном случае массив будет скопирован два раза - на пути к коду JNI и на обратном пути:)

Из-за этого была введена Buffer иерархия классов.И, конечно, команда разработчиков Java создает хороший способ кодирования / декодирования символов:

Charser#newDecoder возвращает вас CharsetDecoder, что может быть использовано для преобразования ByteBuffer в CharBuffer в соответствии с Charset,Существует две основные версии методов:

CoderResult decode(ByteBuffer in, CharBuffer out, boolean endOfInput)
CharBuffer decode(ByteBuffer in)

Для максимальной производительности вам нужна первая.Внутри него нет скрытых выделений памяти.

Следует отметить, что кодировщик / декодер может обслуживать внутреннее состояние, поэтому будьте осторожны (например, если вы отображаете из 2-байтового кодирования и входной буфер имеет одну половину символа ...).Также кодер / декодер не безопасен для потоков

1 голос
/ 21 января 2010

Существует очень мало причин для "сжатия" строки в байтовом массиве.Я бы порекомендовал написать функции C, которые бы принимали в качестве параметров строки utf-16.Таким образом, нет необходимости в каком-либо преобразовании.

...