Pull to refresh

Comments 40

Ну и напоследок — не используйте тип Boolean. Мне трудно придумать ситуацию, где он реально может потребоваться

Здесь можно поспорить — Boolean хорошо использовать, когда нужно именно три состояния, например, True/False/Not Set и Yes/No/Don't Know.
Ну и напоследок — не используйте тип Boolean. Мне трудно придумать ситуацию, где он реально может потребоваться
Коллекции
Да, кстати, любой Generic будет работать только с Boolean, Long, Integer и т.д., т.е. не с примитивом
+ Boolean нужен при использовании рефлексии
Вы храните в коллекциях Boolean? Сомнительно.
Иногда приходится.
Возможно, если у вас в коллекции действительно много значений и вы не противитесь сторонним библиотекам, есть смысл попробовать trove.
Например java.util.Collections.newSetFromMap(Map<E,Boolean> map) как раз таки требует мапу с Boolean.
Если Вам нужно хранить 3 состояния, то это уже не boolean. Для этого отлично подойдут перечисления.
Мне так не кажется — зачем создавать дополнительные сущности, если имеющиеся идеально подходят? Тем более что при правильном использовании Boolean'а в системе находятся только два инстанца. Откуда в таком случае взяться проблемам с памятью?
Потому что null это не «Not Set» и null это не Don't Know.

>> при правильном использовании Boolean'а в системе находятся только два инстанца
Два инстанса примитива. Boolean это прежде всего объект и помимо значения value он как и каждый объект содержит заголовок + возможные выравнивания для кратности 8 байтам + Вы должны хранить ссылку на этот объект. Согласитесь, это не мало для того чтобы запомнить 1 бит.
Нет, два инстанца именно Boolean'а. Соответсвенно оверхеда на заголовок + возможные выравнивания для кратности 8 байтам нет. Согласен, есть оверхед на ссылку.

Потому что null это не «Not Set» и null это не Don't Know.
Всё зависит от того какое логическое поределение мы ему дадим. 2+2 != 4 в кольце вычетов по модулю 3, потому что так определено сложение. Также мы можем определить и использование Boolean'а в зависимости от задачи.
Но заметьте — при использовании Enum'а, тоже будет оверхед на ссылку.
Будет не только оверхед на ссылку, но и оверхед на поле name внутри перечисления. Но в случае перечисления мы всегда уверены что будет создан только один объект перечисления. В случае же Boolean мы не можем этого гарантировать, так как инициализация этого поля может идти через new Boolean и осуществляется в месте где мы не можем ничего изменить.
>>Нет, два инстанца именно Boolean'а
На самом деле все будет зависеть от того как будет создаваться объект булеана.
Если через Boolean a = new Boolean(false); то прав я.
Если через Boolean a = false; то правы Вы.
Под правильным использованием Boolean'а я и имел ввиду отсутствие таких конструкций =)
Тогда уж правильнее всего:
Boolean a = Boolean.FALSE;
Что и сделает в итоге вторая строка через valueOf. А первая строка вообще как бы и не рекомендуется в явадоке, как помнится.
Немогу не поделится ссылкой (http://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&ved=0CC0QFjAA&url=http%3A%2F%2Fdomino.research.ibm.com%2Fcomm%2Fresearch_people.nsf%2Fpages%2Fsevitsky.pubs.html%2F%24FILE%2Foopsla08%2520memory-efficient%2520java%2520slides.pdf&ei=v3QyT4yiIeXm4QTwt5ySBQ&usg=AFQjCNEPtILphv6DOcMj3D4qZLKPmBkFxw&sig2=MNFjDK7kl4nVJ9Qbhagosg) на ужасы съедамой объектами памяти, большая часть презентации — про то насколько страшен HashSet.

Для себя заметил в последнем проекте что когда пытаешься писать быстрый код, используя кэши и маппинг чтобы не лазить лишний раз в хранилище данных, в реальности проблемы всплывают не с производительностью, а как раз с нехваткой памяти и частыми GC, выгружающими по 1-2 Гб из heap'a, приходится писать свои велосипеды и «низкоуровневый» код.
Да я рад что с отрицательной кармой хотя бы главная страница открывается, а большего и так нельзя вообще ничего сделать)
Да, согласен. Как только модель становится большой и в кеше начинает хранится много объектов — память начинает играть очень заметную роль.
Спасибо за ссылку.
Хороший дизайн всегда идет в ущерб памяти и производительности. Благо на данный момент это дешевые ресурсы: память стоит копейки по сравнению с разработкой высого оптимизированного кода. Другое дело десктопы и устройства с ограниченной памятью типа смартфонов и планшетников… Видимо поэтому java заняла прочное место на рынке серверов и совсем угасла в десктопной среде.
UFO just landed and posted this here
UFO just landed and posted this here
В спецификации где-то об этом сказано? Если нет, то «Объекты класса А и B потребляют одинаковое количество памяти. „ вовсе не факт.
UFO just landed and posted this here
Да, из-за выравнивания. В Oracle и Open JDK это действительно так. Не думаю что остальные отошли от них.
Не парьтесь, это у автора такая фишка в цикле статей — наблюдать за отдельно взятой JVM и подсчитывать в ней байтики на синтетических примерах, совершенно в отрыве от контекста и задачи :)
Ну тогда покажите мне JVM в которой это не так и я сниму перед Вами шляпу.
Тот же HotSpot JVM, но на 32-битной платформе.
а какая разница сколько памяти занимают 100 полей в классе? Основные затраты памяти и проц.времени в почти всех жава-приложениях будут на:
— ожидание ответа от базы данных
— разбор хмл-ов
— орм-маппинг
узкое у вас представление о «почти всех жава-приложениях». Вот, например, Мартин Фаулер описывает приложение в котором все хранится в памяти, думаю им приходится задумываться сколько занимают объекты джава.
да уж какие тут шутки
Простите, долго себя сдерживал, чтобы не комментировать вашу серию «статей» на эту тему, но терпеть больше не могу.

Для придания большего драматизма, все расчеты и цифры будут приводится для 64-х разрядной HotSpot JVM.

Вообще говоря, ВСЕ что вы пишите имеет (а порой и не имеет) смысл только для HotSpot JVM, одной из реализаций (хоть и самой распространенной) JVM.

Денормализация модели

Используем смещение в свою пользу

Факт выравнивания нигде не специфицируется. Даже в рамках одной JVM. Тот же Hotspot, например, может быть портирован на абстрактную платформу, где вообще нет необходимости в выравнивании полей.
Более того, на 32-ной платформе ваш пример абсолютно бесполезен. Я помню, что вы говорите только о 64-ном HotSpot'е, но какой смысл писать 64-bit-only Java-приложение?
Следовательно, все ваши выводы бесполезны для большей части Java-приложений.

Иногда глупо жертвовать процессорным временем ради экономии памяти, учитывая что никакой экономии может и не быть вовсе.

Экономия одного поля в классе — это не экономия, а бред. И любой Java-программист, который «экономит на полях» из приведенных вами соображений, IMHO, рано или поздно превратится в говнокодера.

Иногда нету никакого смысла использовать byte вместо int, так как за счет выравнивания разница все равно может нивелироваться.

А иногда можно сделать четыре byte поля, которые будут занимать ровно 4 байта засчет переупорядочивания полей. Но опять же, считать выравнивание в Java-классах себе дороже…

Замена одного поля Integer на int позволит сэкономить 16 байт памяти на объект.

Правда, если значение Integer'а в пределах -127-128, то на каждое значение ровно один объект в памяти. А если покрутить ручки HotSpot'а, то диапазон можно сделать еще больше.
А если JVM не оракловский? Тогда там вообще все по-другому!
И сборщик мусора может даже не заметить пачки аллоцированных примитивных заверток.
Кроме этого, есть еще техника Object-инлайна, тогда большая часть оверхедов на эти завертки может нивелироваться.
Опять же, Вы делаете какие-то гипотетические выводы, абсолютно не обращая внимания на сами оптимизации в реализациях JVM.

Ну и напоследок — не используйте тип Boolean.

Про разные use-cases уже написали в комментариях.

Но для реальных приложений объем в 4 ГБ не досягаем в виду того, что часть адресного пространства используется для установленных периферийных устройств, например, видео карты.

Простите, но это полный бред.
Досягаемость 4 Гб зависит ровно от операционной системы и ее настроек. Тот же Windows XP имеет системное ограничение в 2 Гб адресное пространство (3 Гб в более новых версиях при соответствующих настройках). Причина: оптимизация трансляции адресов. В то же время на Linux'ах, если не ошибаюсь, границы уже сломаны и приложения могут использовать все адресное пространство.
Ну и конечно же, часть доступного пользовательскому приложению адресного пространства действительно занята системой и системными библиотеками.

Поэтому разработчики виртуальных машин решили сэкономить на размере ссылок и ввели опцию -XX:+UseCompressedOops.

Просто уточну: разработчики одной виртуальной машины.
Будем считать, что эта оговорка была сделана случайно ради «красного словца».

Если кому-то кажется, что этот комментарий несет строго негативную оценку, то это правда. Я крайне негативно оцениваю эту статью. Примерно как «белый» SEO-шник оценит «черное» SEO. Или как физик-ученый оценит лже-науку.
Я признаю, что многое из написанного действительно справедливо для amd64-x86-compatible windows-version Sun/Oracle HotSpot JVM, но сделанные автором выводы уже поддаются сомнению в отношении того же HotSpot'а на других платформах, а если говорить о других JVM, то эти выводы просто смешны и бесполезны.
Те же мысли были, но писать много лень, в прошлых статьях пытался, да всё впустую :) Предполагаю, что автор всерьёз не оптимизировал огромные приложения на память и прочие ресурсы. О распределении полей не то чтобы в последнюю очередь надо думать, а скажем так вообще никогда. Писал я и на javame очень много, даже там таким заниматься крайне странно. Ну, размер байт-кода ещё бывало приходилось ухитряться пожимать, но какую-то там непонятную совершенно для java «память» — непонятно. Без ориентирования на строго конкретную реализацию (и даже версию) JVM это совершенно бессмысленно, а это означает, что в Java это бесполезно, не тот инструмент это просто, вот и всё.

З.ы. небольшая поправочка:
Досягаемость 4 Гб зависит ровно от операционной системы и ее настроек. Тот же Windows XP имеет системное ограничение в 2 Гб адресное пространство (3 Гб в более новых версиях при соответствующих настройках). Причина: оптимизация трансляции адресов. В то же время на Linux'ах, если не ошибаюсь, границы уже сломаны и приложения могут использовать все адресное пространство.
Не понял про трансляцию. Мы же видимо про 32-битные системы. Но ведь тут «досягаемость» определяется фактически аппаратно, на 32-битной платформе (предположим, intel) приложение не может никак «сломать границы», ну просто физически. Разумеется, линукс или другой тип системы тут непричём. Если про всякие PAE, то они никак не помогают адресовать процессу больше 4гб, конечно же.
приложение не может никак «сломать границы», ну просто физически.

Здесь я имел в виду, что в отличие от Windows под линукс нет дополнительных ограничений на адресное пространство, т.е. могут использоваться все 4 Гб виртуальной памяти. Но вы правы, выразил я эту мысль коряво :)
Да, мне пофиг на размер объекта. Мне важно, чтобы код легче было поддерживать. Поэтому у меня контейнер будет повторять БЛогику, пока я не увижу, что это узкое место и тут нужно и можно пожертвовать качеством кода ради перформанса или памяти. если у меня синглетон висит в памяти и у него 100 полей Boolean, последнее о чем я буду думать это о его размере. Тем более вся оптимизация под хотспот почемуто.
«Во втором случае у нас есть тысяча ссылок на двумерные массивы!»

может всё же «1000 ссылок на массивы длины 2»?
Sign up to leave a comment.

Articles

Change theme settings