Ява: int->String

salko1

Взялся тут изучать яву с основ. Придумываю-пишу всякие ламерские примерчики, в частности прогу, которая генерит N случайных интов, и в файл записывает. Получилось что-то типа:

FileWriter fw = new FileWriter("Out");
for(int i=0;i<N;i++)
{
Integer rnd = new Integerint100*Math.random;
fw.write(rnd.toString+"\n");
}
fw.close;

Работать-то работает, но есть вопросы: Получается, что в результате работы такого цикла сгенерируется N Integer'ов и N String'ов в куче (или как это в яве называется ) Следовательно, как я понимаю, будет потеря производительности, так как, замусорив память, мы "приблизим" момент сборки мусора? А как тогда инт в стринг преобразовать, не генеря объектов? Можно ли PrintWriter как-то прикрутить к работе с файлами?

anton7805

А как тогда инт в стринг преобразовать, не генеря объектов? Можно ли PrintWriter как-то прикрутить к работе с файлами?
Printwriter тут тебе никак не поможет,потому что он неявно так же создает обертку для примитивных типов ,а потом преврящает их в строку.
Ты не парься по поводу засирания оперативки- gc все удалит , когда время придет
А если уж очень охота сэкономить - то пиши в файл не строки а прям интежеры.

rosali

яву с основ
Как можно не зная даже основ Явы рассуждать о производительности отдельных конструкций? Ты может быть исходники используемой тобой JVM читал?

kokoc88

Можно было написать:
int n = 10;
n+"\n";

koly

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

Hastya

Ты гений.
Можно еще круче написать:

FileWriter fw = new FileWriter("Out");
String out = "";
for(int i=0;i<N;i++)
{
Integer rnd = new Integerint100*Math.random;
out = out + rnd.toString+"\n";
}
fw.write(out);
fw.close;

Тогда будет создано в два раза больше объектов!

salko1

Ну, то что String'и лишние создадутся при "+" я и так догадываюсь. Облажался, конешно, лучше, наверно fw.write(s);fw.write("\n"); Но вопрос-то в другом!

kokoc88

В чём вопрос? Сборщик запустится только тогда, когда это будет необходимо. Есть два варианта запуска java, в которых сборщик работает по-разному: как интерактивное приложение или как серверное. В твоём конкретном примере сборщик отработает настолько быстро, что никому от этого плохо не станет. Да и вообще сложно придумать пример, когда языки со сборщиком мусора потеряют производительность из-за создания кучи объектов. В конце-концов, они все под это заточены.

Hastya

Integer.toString(n)

kokoc88

Это не ответ на вот эту часть вопроса: "не генеря объектов". Думаю, что ответ как раз: "никак".

Dasar

> "не генеря объектов". Думаю, что ответ как раз: "никак".
а так?

for (int i = 1000000; i > 0; i/=10)
{
fw.write('0'+n/i);
n = n % i;
}

kokoc88

Ну я так и предложил, но мне кажется, что '0'+n/i у тебя делает новый объект String.

Hastya

Integer.toString(int) не генерит никаких объектов.
Автору поста же ботать PrintWriter-ы.

Dasar

> Integer.toString(int) не генерит никаких объектов.
а строка откуда тогда берется? из параллельного мира?

Dasar

> '0'+n/i у тебя делает новый объект String.
он делает новый char, а не string
а char - это всего лишь доп. локальная переменная (или, вообще, регистр а не объект.

kokoc88

Ну ботай:
    public static String toString(int i) {
if (i == Integer.MIN_VALUE)
return "-2147483648";
int size = (i < 0) ? stringSize(-i) + 1 : stringSize(i);
char[] buf = new char[size];
getChars(i, size, buf);
return new String(0, size, buf);
}

kokoc88

Да, ты прав. Но если ты поглядишь как оно печатает int, то у тебя там всё равно создаётся String. А самым точным ответом на вопрос, может быть JNI. Наверно.

Dasar

> Но если ты поглядишь как оно печатает int, то у тебя там всё равно создаётся String
но, я то печатаю char, а не int
строка вроде не должна создаваться.

Hastya

Все сложнее на самом деле

switch(i) {
case Integer.MIN_VALUE: return "-2147483648";
case -3: return "-3";
case -2: return "-2";
case -1: return "-1";
case 0: return "0";
case 1: return "1";
case 2: return "2";
case 3: return "3";
case 4: return "4";
case 5: return "5";
case 6: return "6";
case 7: return "7";
case 8: return "8";
case 9: return "9";
case 10: return "10";
}
char[] buf = (char[]perThreadBuffer.get;
int charPos = getChars(i, buf);
return new String(buf, charPos, 12 - charPos);

Короче, забейте на оптимизацию.

kokoc88

Сложение чаров = инт. Хотя печать инта может сразу попасть на вывод (в native code согласен.

kokoc88

Этот код у тебя какой давности?

Dasar

> Сложение чаров = инт
Забыл
тогда так (смысл в том, что печатать по одну символу, overhead-а, конечно, больше, зато никаких новых объектов):

for (int i = 1000000; i > 0; i/=10)
{
fw.writechar'0'+n/i;
n = n % i;
}

kokoc88

Да, так можно. Сдаётся мне, пока оно будет печатать таким образом, сборщик мусора успеет раза два-три отработать. %)

bobby

С чего бы это вдруг? Всего около 7 итераций. Хотя скорость зависит от write конечно.

Dasar

Если Writer не буферизированный, то точно успеет.

bobby

Да, возможно.

kokoc88

Короче, мораль такая, что нефиг заботиться о том, о чём уже позаботились. Код для алокации и удаления объектов и строк, быстро и от балды написанный на С++, будет работать медленее, чем Джава. (Конечно, можно написать на С++, чтобы было быстрее, я этого не отрицаю. Но задача будет нетривиальной.)

Dasar

Даже если буферизированный, то overhead-ы на лишние вызовы write-ов скорее всего будут выше, чем однократный пробег GC по уборке нагенеренных строк.

Dasar

> Короче, мораль такая, что нефиг заботиться о том, о чём уже позаботились.
все-таки от лишних аллокаций лучше, конечно, избавляться. те же сложения строк лучше по реже делать, если возможно.
но в то же время, согласен, что сильно заморачиваться этим не стоит.

psihodog

а бреки кто будет ставить?

Hastya

все-таки от лишних аллокаций лучше, конечно, избавляться.
Я помню, года 4 назад была повальная мода на пулы объектов, любой ORM работал через пул.
В последнее время народ постепенно начинает дозревать, что затраты на пул в современных JVM могут оказаться существенно выше чем создание короткоживущих объектов.
В частности, JDK 1.5 вышел с новым heap layout, где очень много сил брошено на оптимизацию короткоживущих объектов (по статистике Sun - до 90% объектов короткоживующие).

bobby

там ретурны стоят

Dasar

про пул/не пул - понятно.
но про лишние аллокации речь идет про следующие случаи:

string result = "";
for (int i = 0; i < 1000; ++i)
{
result += i.ToString;
}
return result;

вот здесь аллокаций много и все они лишние.

anton7805

афтару: на языках, таких как Java , C# и т.д. не стоит сильно заботить о таких мелочах. Они специально созданы , чтоб проггеры не придумывали каждый раз велосипед и собстственные "крутые" методы, теряя на это время и допуская ошибки. Лучше вечером попить пивка ,чем часами тестировать собственные творения.

Hastya

1.5 такие вещи свертывать не умеет...
Возможно, что-то на этот счет придумали в Mustang, где куча всяких наворотов с оптимизацией.
Понятно, что X = A + B + C; будет свернут в StringBuffer, с циклами сложнее.
Опять же, рискуя нарваться на Глебиуса, скажу, что оптимизировать надо все-таки с профайлером в руках, а не абы как.

Dasar

> скажу, что оптимизировать надо все-таки с профайлером в руках, а не абы как
Полностью согласен.

RED-GREEN

>Лучше вечером попить пивка ,чем часами тестировать собственные творения.
Это зачот б/п. Слава богу, что мой любимый софт не пишут в россии.

enochka1145

А где? В Индии?

bobby

А мой любимый софт - IntelliJ IDEA - пишут в России!
Оставить комментарий
Имя или ник:
Комментарий: