Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Java [игнор отключен] [закрыт для гостей] / Экономно расходование памяти / 21 сообщений из 21, страница 1 из 1
10.06.2014, 12:32
    #38666209
rema174
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Экономно расходование памяти
Подскажите приемы для экономного расходования-снижения памяти, используемой приложением. По этой теме не так много материала. Иногда встречаются такие советы:

Случай 1, вместо этого:
Код: java
1.
2.
3.
Elem e;
e = new HeavyElem();
e = new HeavyElem();

делают так:
Код: java
1.
2.
3.
4.
Elem e;
e = new HeavyElem();
e = null;
e = new HeavyElem();



Случай 2:
передавая в метод объект класса, перед выходом из метода, делают:
Код: java
1.
object = null;



Случай 3:
Предлагают использовать Trove library для коллекций, насколько это актуально?
...
Рейтинг: 0 / 0
10.06.2014, 12:41
    #38666223
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Экономно расходование памяти
rema174Подскажите приемы для экономного расходования-снижения памяти, используемой приложением.
Java Memory Profiler - самый важный приём. Превентивные оптимизации - зло.
rema174Случай 1, вместо этого:
Код: java
1.
2.
3.
Elem e;
e = new HeavyElem();
e = new HeavyElem();

делают так:
Код: java
1.
2.
3.
4.
Elem e;
e = new HeavyElem();
e = null;
e = new HeavyElem();



Ерунда. Разве что речь о какой-то экстравагантной Java вроде J2ME. И то не факт что там такое нужно.

rema174Случай 2:
передавая в метод объект класса, перед выходом из метода, делают:
Код: java
1.
object = null;



Для аргумента? Ну, бред же.

rema174Предлагают использовать Trove library для коллекций, насколько это актуально?
Ну, актуально иногда. Если у вас большие массивы примитивов, то использованеи оберток повлечет за собой дополнительные расходы по памяти. Тогда можно взять коллекции созданые для примитивов. Почему нет? Или, например, от String отказаться в пользу char[] или даже byte[]. Тоже имеет смысл в качестве оптимизации, а не в качетсве практики.
...
Рейтинг: 0 / 0
10.06.2014, 12:56
    #38666241
rema174
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Экономно расходование памяти
Blazkowicz,
насчет первых двух случаев согласен, ерунда
...
Рейтинг: 0 / 0
10.06.2014, 16:27
    #38666594
Alexander A. Sak
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Экономно расходование памяти
Все не было повода спросить. Тут вроде подходящее место.

А как насчет декларации аргументов final? Встречал в одном проекте обязательность такого. Аргумент -- для увеличения производительности. Сомнения загнал подальше, но они остались.
...
Рейтинг: 0 / 0
10.06.2014, 16:44
    #38666623
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Экономно расходование памяти
Alexander A. SakВсе не было повода спросить. Тут вроде подходящее место.
А как насчет декларации аргументов final? Встречал в одном проекте обязательность такого. Аргумент -- для увеличения производительности. Сомнения загнал подальше, но они остались.
Скомпилируйте класс с final аргументами в методах и убедитесь что байткод не отличается.
...
Рейтинг: 0 / 0
10.06.2014, 16:48
    #38666632
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Экономно расходование памяти
BlazkowiczСкомпилируйте класс с final аргументами в методах и убедитесь что байткод не отличается.
Хотя, в Java 8 в метаинформации класса теперь хранятся и "параметры". Но байт-код метода не должен отличаться.
...
Рейтинг: 0 / 0
10.06.2014, 17:06
    #38666666
Alexander A. Sak
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Экономно расходование памяти
BlazkowiczAlexander A. SakВсе не было повода спросить. Тут вроде подходящее место.
А как насчет декларации аргументов final? Встречал в одном проекте обязательность такого. Аргумент -- для увеличения производительности. Сомнения загнал подальше, но они остались.
Скомпилируйте класс с final аргументами в методах и убедитесь что байткод не отличается.

Так ведь лень. Иначе бы не спрашивал, а сам посмотрел.
...
Рейтинг: 0 / 0
10.06.2014, 18:54
    #38666798
Паша01
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Экономно расходование памяти
Alexander A. SakТак ведь лень.
Иди компилируй.
...
Рейтинг: 0 / 0
10.06.2014, 20:06
    #38666862
DEVcoach
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Экономно расходование памяти
BlazkowiczСкомпилируйте класс с final аргументами в методах и убедитесь что байткод не отличается.Ну так у вас и с volatile байт-код не будет отличаться. Это ни о чем не говорит. Важен не байткод, а то, как это на самом деле работает в рантайме.
И final запросто может быть быстрее из-за того, что JIT может более агрессивно оптимизировать доступ к нему. А в каких-то крайних сценариях наоборот может быть медленнее, из-за продолбанных реордерингов, которые могли бы ускорить работу конкретной процедуры.
...
Рейтинг: 0 / 0
10.06.2014, 20:07
    #38666865
DEVcoach
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Экономно расходование памяти
DEVcoachBlazkowiczСкомпилируйте класс с final аргументами в методах и убедитесь что байткод не отличается.Ну так у вас и с volatile байт-код не будет отличаться. Это ни о чем не говорит. Важен не байткод, а то, как это на самом деле работает в рантайме.
И final запросто может быть быстрее из-за того, что JIT может более агрессивно оптимизировать доступ к нему. А в каких-то крайних сценариях наоборот может быть медленнее, из-за продолбанных реордерингов, которые могли бы ускорить работу конкретной процедуры.Тьфу блин, в аргументах ! Тогда мой пост не валиден.
...
Рейтинг: 0 / 0
11.06.2014, 13:16
    #38667509
rema174
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Экономно расходование памяти
набросал два теста, по времени тоже самое, интеренсно какой результат по размеру памяти?
в этом профайлере потеряться можно... если кому-то не трудно измерить, то было бы интересно!

Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
import java.util.ArrayList;
public class TestArrayListCharacter {
        
	public static void main(String[] args) {
				
		int startTime = (int) System.currentTimeMillis();
		
		ArrayList<Character> list = new ArrayList<>();
		
		String string = "Java - это технология, используемая для разработки "
				+ "приложений, которые делают работу в сети Интернет более "
				+ "увлекательной и удобной. Java отличается от языка "
				+ "программирования javascript, который представляет собой "
				+ "простую технологию для создания веб-страниц и выполняется "
				+ "только в браузере.\n";

		char[] charArray = string.toCharArray();
		
		for(short y=0; y<1000; y++) {
			for(short i=0; i<charArray.length; i++) {
				list.add(charArray[i]);
			}
		}
		
		for(int i=0; i<list.size(); i++)
			System.out.print(list.get(i));
		
		int finishTime = (int) System.currentTimeMillis();

		System.out.println("ArrayList<Character>: " + (finishTime - startTime));
		
	}
	
}


Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
import org.apache.commons.collections.primitives.ArrayCharList;
public class TestArrayCharList {

	public static void main(String[] args) {

		int startTime = (int) System.currentTimeMillis();

		ArrayCharList arrayCharList = new ArrayCharList();

		String string = "Java - это технология, используемая для разработки "
				+ "приложений, которые делают работу в сети Интернет более "
				+ "увлекательной и удобной. Java отличается от языка "
				+ "программирования javascript, который представляет собой "
				+ "простую технологию для создания веб-страниц и выполняется "
				+ "только в браузере.\n";

		char[] charArray = string.toCharArray();
		
		for(short y=0; y<1000; y++) {
			for (short i = 0; i < charArray.length; i++) {
				arrayCharList.add(charArray[i]);
			}
		}
		
		for(int i=0; i<arrayCharList.size(); i++)
			System.out.print(arrayCharList.get(i));
		
		int finishTime = (int) System.currentTimeMillis();

		System.out.println("ArrayCharList: " + (finishTime - startTime));

	}

}
...
Рейтинг: 0 / 0
11.06.2014, 14:15
    #38667600
rema174
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Экономно расходование памяти
офигеть, я увеличил цикл до 30000, чтоб по настоящему, и мои замеры показали, что экономия памяти достигает как мин. 78 % для умной коллекции
...
Рейтинг: 0 / 0
11.06.2014, 14:21
    #38667611
Blazkowicz
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Экономно расходование памяти
rema174офигеть, я увеличил цикл до 30000, чтоб по настоящему, и мои замеры показали, что экономия памяти достигает как мин. 78 % для умной коллекции
А что удивляет? Посмотри размер типа char и размер экземпляра Character.
...
Рейтинг: 0 / 0
11.06.2014, 19:02
    #38668055
chabapok
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Экономно расходование памяти
Самое разумное - использовать для экономии тот факт, что оракловская jvm выравнивает каждый обьект по границе кешлайна, который составляет 64 байта на х86(_64) архитектуре.
Делается это для отпимизации многопоточной работы: на жаве один поток с одним обьектом и другой с другим будут работать быстро, тогда как на с++ подобное будет зависеть от того как эти обьекты аллоцировались - можно налететь на false sharing.


поэтому возможны порой странный вещи. Миллион обьектов
class Foo{
int t;
}

и миллион обьектов
class Foo{
int t;
int g;
long p;
}

Должны по идее занимать одинаково, потому что оба обьекта влазят в 64байта.

По этой причине, много мелких долгоживущих обьектов - это не очень хорошо, и если можно без них обойтись, то такой путь следует предпочесть...
...
Рейтинг: 0 / 0
11.06.2014, 19:27
    #38668078
mayton
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Экономно расходование памяти
У меня была идея в POJO объединять строковые поля в одно. И аннотациями описывать.
...
Рейтинг: 0 / 0
12.06.2014, 00:14
    #38668230
Экономно расходование памяти
chabapokиспользовать для экономии тот факт, что оракловская jvm выравнивает каждый обьект по границе кешлайна, который составляет 64 байта на х86(_64) архитектуре.

Доклад с примерами, как это проявляется в разных случаях:
YouTube Video
...
Рейтинг: 0 / 0
12.06.2014, 08:55
    #38668292
rema174
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Экономно расходование памяти
maytonУ меня была идея в POJO объединять строковые поля в одно. И аннотациями описывать.
с разделителем? чтобы доставать потом первый - name, второй - city и т.д.? а аннотации как помогут?
...
Рейтинг: 0 / 0
12.06.2014, 11:34
    #38668340
DEVcoach
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Экономно расходование памяти
chabapokСамое разумное - использовать для экономии тот факт, что оракловская jvm выравнивает каждый обьект по границе кешлайна, который составляет 64 байта на х86(_64) архитектуре.
Делается это для отпимизации многопоточной работы: на жаве один поток с одним обьектом и другой с другим будут работать быстро, тогда как на с++ подобное будет зависеть от того как эти обьекты аллоцировались - можно налететь на false sharing.


поэтому возможны порой странный вещи. Миллион обьектов
class Foo{
int t;
}

и миллион обьектов
class Foo{
int t;
int g;
long p;
}

Должны по идее занимать одинаково, потому что оба обьекта влазят в 64байта.

По этой причине, много мелких долгоживущих обьектов - это не очень хорошо, и если можно без них обойтись, то такой путь следует предпочесть...Вы что-то оооочень сильно путаете.
1) Выравнивание по кэшлайну невозможно в принципе . Потому что не существует инструкции процессора, которая позволила бы ему записать конркетное значение конкретно в начало кэш-линии.
2) Выравнивание по кэшлайну не нужно . Потому что мы никогда не читаем объект целиком. Мы можем прочитать его адрес, его поле, и т.д.. Но мы никогда не вычитываем весь объект полностью сразу же.

Вы все это спутали с выравниванием по 64-битной сетке в памяти. Это да, такое есть. Смысл заключается в том, что бы можно было прочитать конкретное поле объекта за минимальное количество чтений из памяти. Адреса в памяти у нас идут так: 0, 8, 16 ... И если вы запишете Long по адресу 8, то сможете его считать за один раз. А если вы его запишете по адресу 12, то вам сначала придется прочитать адрес 8, взять 4 младших байта, потом прочитать адрес 16, взять 4 старших байта, и потом их объединить. Добавьте к этому проблему с конкурентным доступом (один заканчивает запись по адресу 16, а другой начинает вычитывать два адреса => будет прочитана какая-то хрень).

По этой же причине ваш пример с размерами классов неверен. Первый класс займет 16 байт (12 хеадер + 4 int). А второй займет 12 + 4 + 4 + 8 = 28 + 4 (выравнивание) = 32 байта. Ни о какой привязке к кэшлайнам речи не идет. Это легко можно проверить следующим кодом:
Код: java
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
import org.openjdk.jol.info.*;

public class Layout {

    private static class A {
        int a;
    }

    private static class B {
        int a;
        long b;
    }

    private static class C {
        int a;
        int b;
        long c;
    }

    public static void main(String[] args) {
        System.out.println(ClassLayout.parseClass(A.class).toPrintable());
        System.out.println(ClassLayout.parseClass(B.class).toPrintable());
        System.out.println(ClassLayout.parseClass(C.class).toPrintable());
    }
}

...
Рейтинг: 0 / 0
12.06.2014, 11:36
    #38668343
DEVcoach
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Экономно расходование памяти
chabapokПо этой причине, много мелких долгоживущих обьектов - это не очень хорошо, и если можно без них обойтись, то такой путь следует предпочесть...Иметь много мелких долгоживущих объектов плохо, но по совершенно другой причине - высокая фрагментация хипа в tenured generation, которая может приводить к тормозам GC на мажорных сборках.
...
Рейтинг: 0 / 0
12.06.2014, 11:55
    #38668352
mayton
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Экономно расходование памяти
rema174maytonУ меня была идея в POJO объединять строковые поля в одно. И аннотациями описывать.
с разделителем? чтобы доставать потом первый - name, второй - city и т.д.? а аннотации как помогут?
Ну... не POJO. А скорее Entity с геттерами. Я исходил из предположения что если entity содержит
over 100 полей типа String и каждый объект всегда занимает какое-то место, то на уровне
storage коллекции таких сущностей можно получить выигрыш если объединить эти строки
в одну большую. Getter должен соотв. реализовывать логику извлечения этой сжатой строки
из общего пакета строк. Далее, если наблюдать коллекции по вертикали то можно оптимизировать
некоторые справончые fields (которые содержат ограниченный набор значений {"male"|"female"}) или
соптимизировать поля в которые кладут только одно-байтные (по смыслу) ASCII строки.
...
Рейтинг: 0 / 0
17.06.2014, 09:23
    #38671271
chabapok
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Экономно расходование памяти
DEVcoachПо этой же причине ваш пример с размерами классов неверен. Первый класс займет 16 байт (12 хеадер + 4 int). А второй займет 12 + 4 + 4 + 8 = 28 + 4 (выравнивание) = 32 байта. Ни о какой привязке к кэшлайнам речи не идет. Это легко можно проверить следующим кодом:

Давайте различать кучу и ее дамп. В хипдампе выравнивания нет - это понятно. И ваш код относится к дампу.

А вы попытайтесь воспроизвести false sharing работая с разными объектами из разных потоков. Если получится - это значит, что jvm может положить два обьекта в один 64-байтовый блок.

И сделайте сет из 2млн интов и сравните с сетом на 2 млн лонгов. Память жрать должно одинаково, по крайней мере раньше так было. Поделите размер на 2млн. Должно получится около 64.
...
Рейтинг: 0 / 0
Форумы / Java [игнор отключен] [закрыт для гостей] / Экономно расходование памяти / 21 сообщений из 21, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]