А>Их вариант реализации текстовой строки в виже дерева, тоже не плох, А>в ряде случаев может существенно ускорить работу алгоритма.
не очень понятно какого алгоритма кроме канкатенации строк в микробенчмарке
доступ к данным будет очень очень медленным. собственно, если добавить в их бенчмарк получение строки после канкатенации:
print("StringBuilder \"append\" : ");
startTime();
for (int i=0; i < 100; i++) {
StringBuilder sb = new StringBuilder();
for (int j = 0; j < COUNT; j++) {
sb.append(PLUS_STRING);
}
!!!! String x = sb.toString();
}
endTime(100);
print("Text \"concat\" (stack): ");
startTime();
for (int i=0; i < 100; i++) {
PoolContext.enter();
Text txt = Text.EMPTY;
for (int j = 0; j < COUNT; j++) {
txt = txt.concat(PLUS_TEXT);
}
!!!! String x = txt.toString();
PoolContext.exit();
}
endTime(100);
то Text сольет вчистую, а без получения строки канкатенация бессмыслена (нельзя распечатать Text напрямую, нельзя его записать в файл или отправить в поток...). не говоря уже о том, что у StringBuilder есть замечательный метод setLength(0) с применением которого Text сливает в 3-5 раз.
конечно, insert & delete — да, тут Text рвет всех, как-же копировать не надо... только вот GC начнет сильно тормозить из-за огромного кол-ва созданных мелких объектов, а борьба с ним вродебы и была главной целью этого Javolution. да и insert/delete достаточно редкие операции. кроме того, память будет кушать нехило т.к. при delete неиспользованная информация будет оставаться в памяти (причем надолго — пул ведь).
A> Данная штука полезна при реализации вычислительных алгоритмов. A> Например, парсеры из одного формата в другой.
насчет парсеров — очень сильно сомневаюсь, если использовать простейшие оптимизации то Javolution сольет по перформансу... единственная возможная польза — это меньшие GC паузы. но, с современными коллекторами весьма сомнительный плюс с учетом того что создание объекта происходит быстрее чем его взятие из пула, кроме того, GC все равно будет происходить и непонятно что хуже — уничтожение объектов или намного более сложное дерево ссылок.
Здравствуйте, Аноним, Вы писали:
А>У кого есть своё мнение о Javolution
фигня полная. собственно, создание объекта (new DummyObject()) происходит быстрее чем взятие его из пула. это подтверждает их-же тест.
далее — за счет отсутствия инициализации массива нулями они выигрывают в тестах на создание массивов и как следствие — создание длинных строк.
короче, эта фигня полезна только для микробенчмарков и циклов. в реальности их стэковый пул никому не нужен т.к. обычно работа с сообщением происходит не в циклах (например, servlet container не умеет давать на обработку сразу несколько страниц) а по одному.
Re[2]: Javolution
От:
Аноним
Дата:
02.03.05 14:36
Оценка:
Естесьвенно это не панацея от всех бед.
Данная штука полезна при реализации вычислительных алгоритмов.
Например, парсеры из одного формата в другой.
Их вариант реализации текстовой строки в виже дерева, тоже не плох,
в ряде случаев может существенно ускорить работу алгоритма.
В оптимизации простого метода типа
String foo(xxx) {
...
return (String)yyy;
}
использование Text не сильно поможет.
А вот переделка его в
Text foo(xxx) {
...
return (Text)yyy;
}
может дать не плохой эффект.
Например, парсер, который из String в хитром формате строит мат.выражение, которое затем может быть вычислено, сравнено и т.д.
Парсер на вход получает строку, на выходе отдаёт экземпляр выражения. Внутри можно смело все String заменить на Text.
Думаю в этом случае можно ожидать прирост производительности.
На счёт того, что доступ к кешу занимает больше времени, чем простое создание объекта...
В случае создания единичных екземпляров класса — кеширование излижне.
Если же у нас работает цикл, в котором постоянно создаётся куча объектов,
при том, что сохраняются ссылки только на небольшое кол-во созданных объектов — выгода может быть.
Вот пример "из жизни".
Map c ключём состоящим из String + int.
В алгоритми часто требовалось проверить(действительно часто, существует ли такой-то элемент.
Для этого я сначала создавал new Key(String, int) и проверял map.contians(key).
Потом, прикинул, и добавил в Key метод reset и в класс использующий кey добавил переменную класса Кey,
которую при необходимости использовал (key.reset(String,int)).
В итоге с 300мс время работы алгоритма снизилось до 100мс.
Если бы key хранился в кеше, а не как поле класса, думаю, результат не сильно отличался бы.
Короче говоря, я не согласен с вашей пессимистической оценкой javalution
и при первой возможно попробую этой штукой воспользоваться
Re[5]: Javolution
От:
Аноним
Дата:
25.03.05 11:42
Оценка:
Здравствуйте, NotGonnaGetUs, Вы писали:
NGG>Например, парсер, который из String в хитром формате строит мат.выражение, которое затем может быть вычислено, сравнено и т.д. NGG>Парсер на вход получает строку, на выходе отдаёт экземпляр выражения. Внутри можно смело все String заменить на Text. NGG>Думаю в этом случае можно ожидать прирост производительности.
очень очень редкий случай. как правило, результируящая строка куда-то записывается, а для этого нужно из нее сделать String...
кроме того, если все "смело заменить на Text" то мноогие операции замедлятся — например, substring и charAt. как раз charAt и является типичной операцией парсера, а в ней Text сольет очень сильно.
NGG>Потом, прикинул, и добавил в Key метод reset и в класс использующий кey добавил переменную класса Кey, NGG>которую при необходимости использовал (key.reset(String,int)). NGG>В итоге с 300мс время работы алгоритма снизилось до 100мс. NGG>Если бы key хранился в кеше, а не как поле класса, думаю, результат не сильно отличался бы.
дело в том, что в случае кэша нужна синхронизация и/или поиск. если вы вашу функцию reset() объявите как synchronized, то она будет занимать почти в 10 раз больше времени чем честный конструктор. кстати, в JDK 5.0 простые конструкторы стали раза в 3 быстрее по сравнению с JDK 1.4.x, и вообще выделение памяти работает в Java намного быстрее чем malloc() т.к. память не фрагментирована.
в javolution есть два типа пулов — HeapPool, он с синхронизацией, заведомо медленнее чем конструктор и LocalPool, без синхронизации, но, делает поиск в связанном списке. даже микробенчмарк javolutionа честно признается что он сливает (на JDK 5.0, JDK 1.4.x все-таки чуть медленнее)
правда при создании массивов выигрывает, но, при этом "забывает" инициализировать массив нулями каждый раз, семантика сильно отличается, многие алгоритмы заточены на то что массив инициализирован.