boolean — боремся за Java память…

    У Вас когда-либо случались такие ситуации, когда Ваше Java приложение трещит по швам? В моём случае это случилось из-за нехватки доступной оперативной памяти. И, естественно, обнаружилась нехватка в самый неподходящий момент: на носу очередной долгожданный релиз, один из серверов остановлен для обновления кода и данных и реинкарнация старого кода уже невозможна, в ближайшие дни запланировано несколько совещаний и собеседований, что сильно отвлекает от процесса оптимизации — в общем, ЧП не прошло незамеченным.

    К слову сказать, сделай я правильный backup и экстренные работы по восстановлению жизнеспособности прошли бы гораздо более спокойно, но это была бы уже совсем другая история. Итак в моём распоряжении есть код, которому не хватает 15Gb оперативной памяти для нормального функционирования и очень длительный и дорогостоящий процесс запуска (около 5 часов), в ходе работы которого можно только сидеть со скрещенными пальцами и надеятся, что в этот раз заветные слова OutOfMemoryException не появятся в консоли удалённого сервера.
    Не буду описывать всех ухищрений, которые пришлось проделать, чтобы восстановить остановленный сервер в течении трёх дней, но одним своим мини открытием поделюсь — boolean — это не тот тип данных, который Вы хотите использовать в высоконагруженных системах. Внимание вопрос:

    Как Вы думаете, сколько памяти занимает boolean например на Ubuntu server x64?

    Правильным ответом будет: неизвестно и зависит только от реализации JVM.

    Рассмотрим распространённую Sun JVM и прочтем в спецификации виртуальной машины, что boolean типа в ней нет как такового, вместо него используется int! А это означает, что для хранения значения типа «да\нет» используется ровно 32 бита, независимо от архитектуры процессора. Правда в том же разделе мы видим, что произведена оптимизация для работы с массивами boolean, которые преобразуются в массив байт, что даёт прирост доступной памяти в 4 раза. И всё же платить за хранение нолика или еденички семью лишними битами — иногда просто кощунство и издевательство над серверами (особенно при размерах массивов в 500 миллионов элементов).

    Спасением в таких случаях будет класс BitSet, который ведёт себя подобно массиву boolean, но упаковывает данные так, что для одного бита выделяется всего один бит памяти (с небольшими издержками для всего массива). BitSet хранит внутри себя массив типа long, а при запросе или установке значения определенного бита — высчитывает индекс нужного long и пользуясь побитовыми операциями и операциями сдвига производит вычисления над единственным битом.
    Существует еще более интересная реализация BitSet, OpenBitSet — Apache реализация, которая используется для Lucene. Она гораздо быстрее, но упускает некоторые проверки, проводимые в оригинальном BitSet. Что использовать — решать Вам.
    Поделиться публикацией

    Похожие публикации

    Комментарии 140
      +5
      Это мой первый пост на Хабре, потому любая критика или пожелания принимаются в комментах
        –3
        А так бы не принималась?:)
          +1
          Собственно ударение на первой части предложения было.
        0
        Cпасибо за статью, полезная информация.
          +10
          Просто интересно — что за проект такой, который требует 15 гигов оперативы и запускается 5 часов?
            +14
            это-же джава :)
              +4
              Вы думаете на других языках нет проектов с подобной прожорливостью?
              Как я и говорил всё зависит от соотношения цена/качество память/производительность
                +9
                Не аргумент…
                Сейчас видимо модно пинать джаву, но на мой взгляд, если язык/jvm позволяет съедать 15гигов памяти — это ещё не значит что джава прожорливая/тормозная.

                я не астролог, но подозреваю, что 5 часов загрузки — это в основном IO.
                иначе — если приложение 5 часов грузит процессор, чтобы загрузиться — что-то в этом мире не так.
                  +3
                  Всё в мире верно. :) IO + логика обработки потока данных.
                    +3
                    подозреваю, что 15 гиг памяти хавается как раз, что бы избежать дополнительного io
                    0
                    ну да, было бы хуже…
                    +1
                    Таких проектов много. Всё зависит от того, что вам важнее — память или быстродействие. Для нас более приоритетным на данный момент есть быстродействие.

                    5 часов — не совсем чистый запуск, а подготовка данных (импорт) + препроцессинг.
                      +3
                      Все же интересен прикладной момент, т.к. настораживает дизайн программы. В случае больших объемов данных и длительных процессов, желательно разбивать процесс на подпроцессы с точками сохранения состояния. Ведь производительность-то, как говорится, никакая в случае падения конечного процесса.
                        0
                        Для этого есть high availability технологии :)

                        Есть и точки сохранения и модульность — здесь всё хорошо (хотя и не отлично). Т.е. система даже больше чем описана в оригинальном посте, а описание идёт конкретного модуля.
                          +1
                          high availability к бизнес транзакциям не имее никакого отношения. Точнее можно так «пофиксить» проблему, но все же нужно подход менять.

                          … Так вот, как раз, для модуля это и многовато! Даже если идет разложение битовых данных, например, изображение для распознавания образов, то вполне можно сохранять по квадрантам и параллелить их обработку.
                        0
                        Все равно не понятно, что там так долго делать. Система обрабатывает видео в full-hd при запуске или что? Нельзя ли например сделать дисковый кэш и загружать какие-то данные уже обработанными или они всегда новые при загрузке?
                          0
                          Как я и написал, под «запуском» в данном топике я подразумевал полный цикл запуска. Старт веб-сервера, конечно проходит за секунды (точных значений даже не знаю, поскольку они всех устраивают), а вот импорт и препроцессинг отъедают порядка 5ти часов.
                            0
                            Не, понятно, что запуск сервера происходит за секунды, но что программа делает 5 часов? Вот этот импорт и препроцессинг — это обработка графических файлов, видео, построение индексов каких-то? И почему нельзя это дело закэшировать на диск?
                              +1
                              Нет, это обработка огромного кол-ва текстовых данных, как это ни странно :)
                              Дисковый кеш в данном случае служит только для подъёма новых инстансов сервера. Т.е. импортированные единожды данные позволяют запускать несколько веб серверов. Потоковая же обработка затруднена тем, что на данном этапе обработка зависит от уже полученных данных — т.е. пока не удалось построить алгоритм, который бы использовал потоковую обработку (в несколько этапов/прогонов, чтобы учесть зависимость данных) при суммарной разумной скорости всей операции.

                              Реимпорт естественно проходит единожды при поступлении новых данных, правда данные очень часто обновляются.
                          –1
                          Ну слушайте, а есть же вские кеши, key-value базы данных и прочее, многие задачи можно разбить на этапы и т.д. Я все таки думаю, что у вас что-то с алгоритмом, если вы не занимаетесь какой-нибудь там обработкой даннх о погоде или 3д-моделированием со свервысоким качеством, вряд ли вам нужно столько ресурсов.

                          И где тут те товарищи, которые кричат, что железо купить дешевле, чем хорошего программиста?
                            0
                            Чем в данном случае помогут кеши, при обработке данных в память?
                            БД тоже врядли будут сравнимы по скорости. На этапе импорта достаточно сильна обратная связь с уже загруженными данными, потому прийдётся как много писать, так и много читать.
                            Поправте меня, если я не прав.

                            Товарищи уже отписывались, правда в небольших количествах :)
                          +3
                          хабрую вопрос.
                          что это?
                          +2
                          На мой взгляд, было бы лучше сразу рассказать о всех проделанных ухищрениях для восстановления работоспособности приложения. А то сейчас получается, что во всем виноват boolean.
                            +1
                            Скажем так, именно boolean спас меня и дал мне время для более детального рефакторинга проекта.
                              +7
                              Ну, я думаю, что большинству понятно, что не стоит использовать «массив из 500 миллионов элементов» (тем более, если есть очевидные проблемы с памятью), а надо прибегнуть к каким-то другим схемам данных, типа BitSet или другого :) Тут не в boolean дело, собственно, а в общих вопросах архитектуры приложения.
                                +3
                                Ну, мы ведь не знает, что за проект. Не думаю, что стоит судить, не зная вообще никаких деталей.
                                Тем более, что проект делался с упором на производительность в ущерб памяти: скорее всего там огромная куча данных кэшируется из бд и разархивируется при запуске приложения.
                                  +1
                                  Поверте, массив булеанов из 500 миллионов элементов не забивает 15GB RAM.

                                  А касательно: «а надо прибегнуть к каким-то другим схемам данных», я Вам скажу, что массивы простых типов в джава будут занимать гораздо меньше памяти, чем коллекция классов с аналогичными полями
                                    0
                                    Зато он забивает ~1.9 Гб, что тоже внушительно…
                                      0
                                      Вы ошибаетесь, всего ~500 МБ, хотя это тоже не мало.
                                        0
                                        4 байта на 500 000 000 = 2 000 000 000 / 1024 / 1024 = 1 907,3486328125 Мб.
                                          0
                                          Правда в том же разделе мы видим, что произведена оптимизация для работы с массивами boolean, которые преобразуются в массив байт, что даёт прирост доступной памяти в 4 раза.

                                          Т.е. по моим данным: 1 байта на 500 000 000 = 500 000 000 / 1024 / 1024 = 476,837158203125 Мб.
                                            0
                                            Ну это же уже после оптимизации ;)
                                              0
                                              Но для Вас-то она прозрачная.
                              +2
                              Я очень извиняюсь за свою предубеждённость, но мне кажется, что если проект требует 15 Гб оперативки и запускается 5 часов — you are doing it wrong! o_O

                              И вообще, писать на джаве такое… О_о
                                –25
                                Да индусы писали наверно, Ява же для них и придумана, чтоб дров не могли наломать.
                                  +3
                                  Писали отнюдь не индусы, а данные запакованы очень усердно.
                                    +3
                                    Вы считаете, что писать на php намного сложнее?
                                      0
                                      на пхп: засучили рукова и вместо полноценной загрузки xml в память сделали б парсер на strstr() и пихнули бы данные в бд
                                        0
                                        полноценной загрузки?
                                          0
                                          Я умею и на джава работать с БД, но это оказывается медленнее, чем с памятью ;)
                                          Вы действительно думаете, что на ПХП будет быстрее/легче?
                                          –6
                                          Ну 15 Гб мои скрипты не едят, я могу точно сказать.
                                            0
                                            А сколько данных обрабатывается?
                                              –3
                                              Намного меньше :) Но поверьте, в php требования к разработчику строже, чем в Яве, так как там скрипт перезапускается при каждом запросе (а не при запуске сервера), и если он делает что-то лишнее, или долго инициализируется, все будет ощутимо тормозить.

                                              Зато правда, об освобождении памяти думать не надо (хотя в Яве тоже).
                                                +1
                                                >>php требования к разработчику строже, чем в Яве
                                                Поржал, спасибо.

                                                Именно потому, что скрипт перезапускается при каждом запросе, можно покласть хер на многие аспекты, включая управление ресурсами и памятью — все равно скрипт будет выгружен.

                                                Именно поэтому, кстати, в php один из самых говеных сборщиков мусора, который до сих пор течет.
                                                  0
                                                  >> если он делает что-то лишнее, или долго инициализируется

                                                  Скажите, сколько вы писали на Java для web? Там тоже принята модель request-responce, где код выполняется в ответ на обработку http-запроса (посмотрите на сервлеты), но вы почему-то утверждаете обратное.
                                                    –2
                                                    Причем тут сервлеты? Ява-приложение не запускается при каждом запросе. а значит можно писать код хоть левой пяткой, например делая запуск сервера по 5 минут.
                                                      +2
                                                      Слушайте, давайте вы сосредоточитесь секунд на 30, а затем почитаете про сервлеты сходите. Они тут при том, что мы рассматриваем request-response, как в классическом php. Поэтому обработка запроса должна быть так же быстро, как и в предлагаемом вами php.

                                                      То, что приложение может подниматься 5 минут, влияет только на удобство разработки. Если стартует медленно — значит девелопер сам себе злобный Буратино, не более.

                                                      P.S. Вашей логике следовать, так на Си тоже пишут левой пяткой и с меньшей дисциплиной, потому что приложение на Си запускается один раз.

                                                      Или ja va с просто не понял? )
                                            +11
                                            Знаете, не хочу сказать Вам ничего плохого, хотя очень хочется. Вам, возможно, очень нравится писать замечательные нямки на ассемблере и си, используя любые технологии от компила кода в рантайме и сваливания его в стек сегмент на асме и до шаблонов темплейтов с элементами ооп на с++, отлаживать и искать баги сотнями часов, но, когда Вас поставят перед задачей имплементации объемного набора логики и моделей, то, я предвижу, что Вы либо не выполните задачу, либо пойдете читать книги для так нелюбимых вами индусов по Яве / C#. Я не предлагаю вам Яву в микроконтроллеры ПИК или Атмел устанавливать, но и си не место в сегменте бизнес приложений. Для таких как Вы на Баше пишут цитаты в духе "- Продаю Белаз. — А сколько расход по городу?"

                                            P.S. Прошу Хабрасообщество простить меня за этот пост, но, просто накипело.
                                            P.P.S. Возможно я слишком ленив и узколоб, тогда прошу простить меня еще раз, я, наверное что-то неправильно понял.

                                            С уважением

                                            С.
                                              –1
                                              Да нет, вы конечно правы, для каждой задачи свои технологии, но если у вас приложение что-то там обрабатывает, и ему 15 Гб не хватает, либо технология неподходящая, либо алгоритм плохой.

                                              Гугл как-то без сверхмощных компьютеров например обходится :) А у него задачи тоже нешуточные.

                                              Тем более там автор где-то писал, там модели, и т.д. то есть сложная система хранения данных внутри и автор видимо сам не знает. насколько она эффективно и грамотно сделана.

                                              Ну и насчет индусов — ну у меня все же есть ощущение, что создание языков Java и .NET отчасти преследовало цели: возможность использвоания менее квалифицированных разработчиков (=индусов), это еще с Visual Basic пытались сделать в свое время.
                                                +3
                                                Именно. php, кстати, преследует ту же цель.
                                                  0
                                                  ну у меня все же есть ощущение, что создание языков Java и .NET отчасти преследовало цели: возможность использвоания менее квалифицированных разработчиков (=индусов), это еще с Visual Basic пытались сделать в свое время.
                                                  Я подозреваю что это ещё с Фортрана началось.
                                                    0
                                                    Хотите сказать, что если кодер на плюсах вдруг переходит на Джаву/.НЕТ, он сразу же тупеет? Эти языки создаются для того, чтобы акцентировать внимание на том, что важно, например, интерфейс, бизнес-логика, очень сложная архитектура, а не считать каждый байт памяти. Для того, чтобы грамотно писать на нете/джаве тоже надо иметь соображалку.
                                                      –1
                                                      Ну в Яве тоже не все гладко, есть заморочные XML-конфиги, есть огромные громоздкие приложения с кучей библиотек-на-все-случаи-жизни.
                                                        +2
                                                        Хороший ответ по существу.
                                                        Вот php разжижает мозг, это да, это обычно заметно.
                                                0
                                                Касательно запуска, я уже ответил здесь.

                                                Данный проект достался мне в наследство, но я вам скажу, ведёт он себя более стабильно и предсказуемо, чем многие другие. Рефакторинг, конечно назрел, но не думаю, что это кардинально скажется на описанных параметрах, поскольку платиться временем подготовки ради использования меньшего объема памяти никто пока не согласен.
                                                  –6
                                                  Тада пусть расширяют размер виртуальной памяти, планки новые покупают, своп увеличивают.
                                                  Но вообще для ТАКИХ задач Ява не годится
                                                    0
                                                    Тогда расскажите нам для каких годится?:)
                                                      –1
                                                      Я уже сказал, когда речь идёт о фантастических объемах данных, то реально справляются лишь достаточно низкоуровневые языки типа Си.
                                                        0
                                                          +4
                                                          Хабр — сборище анонимных архитекторов. Панемаю.
                                                            +1
                                                            О, да, все крупнейшие энтерпрайз приложения следовало писать именно на Си ;))
                                                    0
                                                    >>особенно при размерах массивов в 500 миллионов элементов

                                                    А может в консерватории что-то править надо, в смысле не закидывать ваши 500 миллионов обьектов в память все и сразу?
                                                      +2
                                                      про буферизацию слыхали?
                                                      +10
                                                      Странное открытие. Сколько мне приходилось сталкиваться — в большинстве языков тип boolean эмулируется через int (в некоторых через byte или char), также как и есть возможность хранить array of boolean в bitmap'ах, но тогда вы за экономию памяти платите потерей производительности.
                                                      Это также очевидно, как и выравнивание данных по словам.
                                                        +2
                                                        Теперь и я набрал достаточное кол-во энергии Цинь, чтобы это осознать. Надеюсь пост поможет кому-то еще.
                                                          +2
                                                          Рассказывайте дальше, может мы вам еще и IO ускорим раз в 10-20 :)

                                                          Причем, я серьезно.
                                                          Вы как данные читаете и как пакуете?
                                                            0
                                                            Хм, ну начнём с того, что эту часть системы создавал не я, хотя на данном этапе отвечаю за неё именно я.
                                                            Повествование иногда буду упрощать, дабы не вдаваться в дебри слишком глубоко:

                                                            Данные приходят в формате XML, заархивированные. В зависимости от формата архива создаётся дочерний процесс с командой на разархивирование (например «zcat <имя_файла>.gz»), выходной поток которого читается в исходном процессе и парсится. Буферизированные данные ложаться в основном в массивы long и int, хотя некоторая атрибутика кладётся в коллекции — но таких данных не много. Связка данных в основном идёт по индексам соответствующих массивов, но иногда приходится делать вспомагательные «переходные» массивы с индекса одной сущности на индекс другой. Поиск бинарный, т.к. есть возможность создать упорядоченные массивы данных.

                                                            Еще вопросы?

                                                            • НЛО прилетело и опубликовало эту надпись здесь
                                                                0
                                                                Накапливаю в память, как и говорил, с последующим дампом по окончании процедуры препроцессинга.

                                                                Как это ни странно, но архив один (да-да, бывает такое в наше время), и разделять его не желательно из-за зависимости данных, как я и писал. Парсинг SAX'ом. После успешного дампа, на готовых данных поднимаются инстансы веб-серверов.

                                                                Какой этот? Я описываю только импорт и препроцессинг — да они занимают более 5ти часов.
                                                                0
                                                                Вот тут уже написали вопросы.

                                                                Присоединяюсь — как и чем парсится XML, куда потом складывается?
                                                                Сам парсинг XML, если не писать в массивы, сколько времени/памяти занимает?

                                                                Вот еще пример достаточно неочевидного момента, про который многие забывают:

                                                                String func() {
                                                                String s = new String(); s = «миллион символов… »; return s.substring(1,2);
                                                                }

                                                                Sting s1 = func();

                                                                Сколько израсходуется памяти?
                                                                  0
                                                                  Столько, сколько нужно для «миллион символов… ». Достаточно посмотреть исходники:
                                                                  new String(offset + beginIndex, endIndex — beginIndex, value);

                                                                  0
                                                                  Не знаю как у вас в Яве, у нас в php gzip-файлы можно читать через фильтры ввода-вывода, без пайпов (и переключений контекста) и лишних процессов, а после, кстати, можно куда-нибудь сохранять распакованные и распарсенные данные (ч/з сериализацию, например). Уже будет экономия, правда ценой дискового места.

                                                                  Кроме того, возможно, все таки не все данные нужны сразу в памяти? Может, можно их обрабатывать послежовательно, по кусочку? Или сохранять сериализованные данные в много файлов и загружать по требованию.

                                                                    0
                                                                    Как на счет bzip? pbzip?

                                                                    Касательно сохранять данные: здесь
                                                                    Касательно не всё в памяти: здесь
                                                                    0
                                                                    а если в top посмотреть кто упирается в ресурсы? основной процесс или распковщик? и куда в CPU или iowait?

                                                                    если упирается гзип то дело труба — исходные данные ужасны (этож сколько там Гб файл?)

                                                                    если основной процесс — оставить в нем только парсер и повторить прогон, не помогло — значит уперлись в парсер, иначе в основное приложене
                                                                    ну а дальше тюнить то во что упелись
                                                                    +1
                                                                    прочитал не IO, а IQ =)))
                                                                      0
                                                                      Я тоже сначала, потом подумал, что мне его ускорять точно не стоит, разве что повышать и перечитал в правильном варианте :-)
                                                                        0
                                                                        /me глядел недавно на эмблему Google IO, поэтому неоднозначных ассоциаций не возникло :)
                                                                  0
                                                                  Более того, даже эти byte или char частенько могут оказываться word-aligned.

                                                                  В общем, автора топика еще ожидает множество интересных открытий в мире реальных вычислений :)
                                                                  –7
                                                                  Мне кажется вам пора перебираться на Си
                                                                    0
                                                                    Не факт. Вожможно это просто предубеждения о Java.
                                                                      –4
                                                                      Просто для оперирования с такими мега объемами данных годятся только низкоуровневые языки, все остальное дает очень большой оверхед. Вот почему то кодеки не пишут на яве, только на си
                                                                        0
                                                                        Кодеки не сторят данные в память (кроме буфферизации конечно), так что и Си используют не по причине памяти. Для них больше важна скорость, которая достигается с помощью нативных операций.

                                                                        Хотя в чем-то я с Вами согласен. В любом случае в проекте есть модули написанные на С++, так что не без этого.
                                                                          –1
                                                                          В Си можно хотя бы минимизировать количество служебной информации, хранящейся в памяти. И вообще когда появляются такие требования есть смысл пересмотреть постановку задачи
                                                                            +3
                                                                            У Documentum пару версий назад ядро переписали с C/C++ на java… и получили прирост производительности, увеличение надежности, и уменьшение(!) потребления памяти, видимо в EMC не знают того, что знаете вы ;)
                                                                              +1
                                                                              Пару раз при написании задач по обработке данных на Яве сталкивался с необходимостью по отработке массивов данных (компрессия / декомпрессия). Бизнес логику с Явы на си перемещать никто и не предполагал, но, что сделали: компрессор / декомпрессор собрали на си, под каждую аппаратную платформу по-своему закомпилили (имеются в виду оптимизации специфичные для железа) и подвесили через JNI (интерфейс Явы для интеграции с хостом).

                                                                              С уважением,

                                                                              С.
                                                                          0
                                                                          Объем данных тут не причем, кстати.

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

                                                                          На одних кодеках мир не сошелся.

                                                                          Кстати, слыхали не так давно некто Торвальдс реализовал на Си одну функцию, так его реализация обгоняет аналогичную, написанную и соптимизированную руками на ассемлбелере.

                                                                          Если вдруг кто не в курсе, то ключевые слова «openssl, sha1»
                                                                            +1
                                                                            Знаете, если покопаться в имплементации этой ф-ции на асме, то, думаю и ее можно будет оптимизировать. Видите-ли, си — это такой хитрый ассемблер знающий больше «слов», чем железка, отражением которой является асм. Я, конечно, несколько утрирую, но, по сути это действительно так. Си дает некоторый уровень абстракции над железом и асмом, но компилятор си (гнуся) все равно переводит код си в код ассемблера на одной из стадий компиляции и вызова линковщика (если в ваши условия сборки входит его вызов). Я не разбирался в топике названном вами, но, предполагаю, что имплементация на си оказалась быстрее по причине того, что в ней были использован какой-то функционал из стдлиб, оказавшийся более оптимированным, чем «велосипед» написанный для этих целей асмокодерами.

                                                                            С уважением,

                                                                            С.
                                                                              0
                                                                              Да, Вы действительно абсолютно не в курсе топика — stdlib там вообще не при чем, и велосипед-таки изобретал тут как раз Торвальдс, но не суть.

                                                                              Это просто был пример к тому, что Си не всегда сильно быстрее АСМа, а Java не всегда сильно медленнее Си.
                                                                                0
                                                                                Каюсь и иду курить топик. Видимо занятная история. Как показывает история, велосипеды от Торвальдса иной раз заставляют мир задуматься (читайте это с юмором, улыбнетесь ;-).
                                                                        0
                                                                        в си нет булеана.
                                                                          +1
                                                                          уже 9 лет как есть. о С99 что-то слышали?
                                                                        +1
                                                                        >У Вас когда-либо случались такие ситуации, когда Ваше Java приложение трещит по швам?

                                                                        У меня пару раз в жизни случалось GC overhead limit exceeded — это высший пилотаж, я уложился ровно в отведенную память! :)
                                                                          +1
                                                                          Читайте java.sun.com/javase/technologies/hotspot/gc/gc_tuning_6.html#par_gc.oom

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

                                                                          С.
                                                                        • НЛО прилетело и опубликовало эту надпись здесь
                                                                            0
                                                                            Жду аргументов.
                                                                              0
                                                                              Кстати, да, если пишется что-то вроде «GC overhead limit exceeded» то точно как-то не так с объектами работа идёт.

                                                                              Тут надо понимать, что «волшебных» языков у нас нет, каждый имеет вполне реальные трудозатраты на разного рода операции, и их надо учитывать.
                                                                                0
                                                                                Нет, таких слов в логах не наблюдается. Описанное Вами понятно и это воспринимается естественно.
                                                                              0
                                                                              Вопрос не возникает, пока всё хорошо работает. А вообще-то Вы правы, найти ссылку на проблему не сложно.
                                                                                0
                                                                                Это не ссылку на проблему. Это ссылка не эксперимент, который показывает, что JVM умеет хранить boolean в 1 байте.
                                                                                  0
                                                                                  Извините, просмотрел наискосок. Собсственно, об этой оптимизации я говорил в контексте boolean[], но если JVM умеет оптимизировать даже разрозненные переменные — только плюс ей, у меня так не вышло.
                                                                                    0
                                                                                    Локальные переменные компилятор не оптимизирует. А вот JIT имеет право это делать. Но здесь требуется оценивать конкретную реализацию.
                                                                              0
                                                                              ну да то что boolean в int хранится это не открытие.
                                                                              Так же известно что битСет похавает больше производительности чем операции с boolean.
                                                                              А учитывая это habrahabr.ru/blogs/java/76481/#comment_2222720 как то странно. То есть нужна производительность, но вам приходится жертвовать ей что бы в аутмемори не попадать?
                                                                              Где-то у вас серьезные косяки.
                                                                                0
                                                                                Всё упирается в соотношение память/производительность. Где чаши весов склоняются в одну сторону, где-то в другую.

                                                                                А косяки есть везде, куда ж без них.
                                                                                  0
                                                                                  >ну да то что boolean в int хранится это не открытие.

                                                                                  оказывается, что для некоторых — открытие.
                                                                                  0
                                                                                  Прикольная статья конечно, но в реальном приложении boolean's не так много, чтобы наносить значимый hit на само приложение. Думаю лечить надо с другой стороны.
                                                                                    0
                                                                                    ну вам-то лучше знать в каком приложении сколько boolean'ов.
                                                                                    –2
                                                                                    Да, видно кое-кто даже Эккеля не читал прежде чем садится программить на Java.

                                                                                    > Правильным ответом будет: неизвестно и зависит только от реализации JVM.
                                                                                    Зачем вот такую ерунду писать? Есть стандарт, который вы ниже сами же цитируете. Int для boolean, возможна оптимизация до byte для массивов boolean.
                                                                                    Что здесь «неизвестного»? Ничего.
                                                                                    Может ли внезапно быть например два байта в какой-нибудь реализации JVM? Не может, ибо спецификация запрещает. А значит далеко не _только_ реализация JVM решает.

                                                                                    Незачет вобщем.
                                                                                      +4
                                                                                      Спасибо за критику — за ней и пришел. Критика стимулирует рост.

                                                                                      Как Вы думаете, сколько людей прочли Эккеля прежде(!), чем садиться программировать что либо? Сдаётся мне всё приходит с опытом. Надеюсь, для кого-то эта статья превратиться в стимул или опыт.
                                                                                        +1
                                                                                        Пожалуйста. Рад что конструктивно относитесь к этому.
                                                                                        +1
                                                                                        >> Что здесь «неизвестного»? Ничего.
                                                                                        >> Может ли внезапно быть например два байта в какой-нибудь реализации JVM? Не может, ибо спецификация запрещает.

                                                                                        Вы не правы. В цитируемом фрагменте спецификации говорится о том, как представляются операции над типом boolean в class-файле.

                                                                                        JVMS не описывает как затем эти операции должны компилироваться в нативный код JIT или AOT компилятором.

                                                                                        Последний может оптимизировать хранение и операции на boolean любым удобным ему способом.

                                                                                          0
                                                                                          Т.к. оптимизация должна быть прозрачной, нас не особо интересует что там.
                                                                                          Иначе можно и про си написать что-то подобное — вы же не знаете всех оптимизаций производимых gcc например — но это не важно если оно не может поломать ваш код.
                                                                                          Здесь поломатся ничего не может, это не а++ + а++
                                                                                          Зачем эти «сенсационные статьи» в которых инфо вроде «boolean типа в ней нет как такового, вместо него используется int!» преподносятся как откровение или вообще как новость? Это не новость, это общеизвестные вещи.
                                                                                            0
                                                                                            Это верно. Смысл статьи мне тоже непонятен.

                                                                                            Я лишь указал на ошибку в вашем предыдущем сообщении…
                                                                                          0
                                                                                          Элементарно может хоть 100 байт занимать. Например, если для каждого объекта хранится куча служебной информации например для GC. (Я не говорю что так происходит на самом деле, но если написать неэффективный по памяти GC, то вполне может)
                                                                                            –2
                                                                                            Такое можно утверждачть и для int, и long и вообще сказать что ничего не известно, но речь ведь не о том.
                                                                                          0
                                                                                          Рассмотрим распространённую Sun JVM и прочтем в спецификации виртуальной машины, что boolean типа в ней нет как такового, вместо него используется int!

                                                                                          Если все же прочитать текст по приведенной ссылке, то можно узнать, что int используется только для операций (для вычислений выражений), а при создании массива boolean'ов будет создан массив байтов (как и в подавляющем большинстве языков, кстати).

                                                                                          The Java virtual machine does directly support boolean arrays. Its newarray instruction enables creation of boolean arrays. Arrays of type boolean are accessed and modified using the byte array instructions baload and bastore. <.blockquote>
                                                                                            0
                                                                                            О чём я и написал в посте:
                                                                                            Правда в том же разделе мы видим, что произведена оптимизация для работы с массивами boolean, которые преобразуются в массив байт, что даёт прирост доступной памяти в 4 раза.
                                                                                              –1
                                                                                              Блин вы хотя бы узкое место своего монстра нашли?
                                                                                                0
                                                                                                Монстр прекрасно работает, а люди которые им пользуются даже не знают о том, что скрыто за RESTfull API.

                                                                                                Узкое место в данном случае — архитектура. Но с изменениями архитектуры прийдётся смириться с множеством изменений производительности или недоступности некоторых операций.

                                                                                                В итоге прошла волна оптимизации, которая дала время более детально обдумать и обсудить в команде возможные изменения.
                                                                                                0
                                                                                                В документации нигде не сказано, что это оптимизация, а не исходное решение. Скорее наоборот: для оптимизации скорости вычисления выражений в них используется 4-байтовое представление boolean.
                                                                                                  0
                                                                                                  Instead, expressions in the Java programming language that operate on boolean values are compiled to use values of the Java virtual machine int data type.

                                                                                                  The Java virtual machine does directly support boolean arrays
                                                                                                    0
                                                                                                    Извиняюсь — рано отправилось :(
                                                                                                      0
                                                                                                      Здесь сказано, что для выполнения операция над boolean-данными используются значения типа int. Как я и сказал.

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

                                                                                                      Из этого никак не следует, что int — «родное» представление, а «byte» — оптимизация.
                                                                                                        0
                                                                                                        Очевидно мы с Вами по разному трактуем английский текст, в любом случае, это не стоит того, чтобы спорить.
                                                                                                      0
                                                                                                      Исходя из нижеприведенного, я посчитал, что это оптимизация:
                                                                                                      Instead, expressions in the Java programming language that operate on boolean values are compiled to use values of the Java virtual machine int data type.

                                                                                                      The Java virtual machine does directly support boolean arrays…
                                                                                                  0
                                                                                                  Битсет штука хорошая, когда для одного объекта надо использовать большое количество переменных. Но такое получается далеко не всегда. Плюс за это приходится платить процессорным временем. Я тоже одно время пытался экономить на спичках, в итоге пришел к выводу что лучше докупить еще памяти, благо она масштабируется куда дешевле чем процессорное время.
                                                                                                    0
                                                                                                    Иногда даже спички стоит считать. Да и задача, как понятно из топика, стояла запустить остановленный сервер в короткое время. Для этого оптимизация boolean[] -> BitSet подходит просто идеально.
                                                                                                      0
                                                                                                      Ну, как оригинальный костыль — возможно. Если имеются огромные массивы boolean.
                                                                                                    0
                                                                                                    А что стало со скоростью операций после перехода на специальные битовые массивы?

                                                                                                    Выше написали, что скорость работы типа должна страдать из-за лишних операций, но мне кажется, что это вообще не очевидно и требуется эксперимент.

                                                                                                    Вы замеряли, как ведет себя GC во время работы и вообще, что творится с памятью? Проект нестандартный, если напишете статью с цифрами, будет очень интересно.
                                                                                                      0
                                                                                                      Дело в том, что во время повседневного функционирования приложения создание/удаление данных не происходит в таком кол-ве, в котором эти данные в памяти хранятся — замерять работу GC не было особого смысла до сих пор. А переход на битовые массивы не ударил по скорости, поскольку битовые данные носят абсолютно второстепенный характер и используются при построении HTTP ответа.

                                                                                                      Касательно статьи с цифрами — посмотрим, что можно сделать.

                                                                                                      0
                                                                                                      Вспоминаю статью на Хабре о сортировке habrahabr.ru/blogs/algorithm/73726/… может дело не в платформе, а в методе обработки данных?…
                                                                                                        0
                                                                                                        Да, хорошая статья, согласен. Но к объему памяти это никак не относится, если я всё верно понял, а статья изначально именно про память.
                                                                                                        +1
                                                                                                        Сделаю предположение, что исходные данные хранятся в огромном XML, а 5 часов идет его загрузка в память перед тем, как начать вычисления ))))

                                                                                                        К теме. На архитектуре x64 указатели занимают 8 байт, что естественно сильно сжирает память. В jdk 7 обещали compressed pointers, которые сокращают указатель до 32 бит
                                                                                                          0
                                                                                                          С XML вы угадали.

                                                                                                          А вот, про 5 часов загрузки в память перед вычислениями — Вы ошиблись, как описано в комментариях выше, 5 часов — это полный цикл обработки сырых данных.
                                                                                                            +1
                                                                                                            Была у нас в банке задача: нужно сделать конвертер из оперативных данных (сырых) в аналитическую базу. Естественно для аналитической платформы важна скорость выдачи актуальных данных. Полная заливка из одной базы в другую занимала в single user mode от 40 минут, при конкурентной работе значительно больше. А нужно выдавать данные за последние пару минут. Посидел, проанализировал и сдел инкрементарную репликацию, т.е. обрабатываются только свежие данные, а не все, и строятся или обновляются связи, соответственно только для них.
                                                                                                            Естественно этап анализа и имплементации занял порядочное время (у меня пару месяцев), но оно не сравнимо с теми затратами, которые вы тратите ежедневно.
                                                                                                            +1
                                                                                                            вообще оно есть уже в 1.6u14 (http://en.wikipedia.org/wiki/Java_version_history#Java_SE_6_Update_14)
                                                                                                            0
                                                                                                            Тоже недавно словил OutOfMemory в процессе загрузки программой на Java большого объёма данных в БД. Попробую воспользоваться вашим опытом, может и в моём случае поможет.
                                                                                                              –1
                                                                                                              У вас 15 гигов boolean-переменных в памяти? Не на стеке, как я понимаю. Объекты класса Boolean занимает в памяти больше чем просто boolean, кстати
                                                                                                                0
                                                                                                                Я в курсе. Это естественно.
                                                                                                                Про 15 Гигов boolean переменных здесь уже обсуждалось.
                                                                                                                0
                                                                                                                Пара вопросов:
                                                                                                                Как использование BitSet повлияло на производительность?
                                                                                                                Как вы заменили во всем коде boolean на BitSet? Простым find/replace?
                                                                                                                Если я правильно понял, это какое-то внутренне приложение и у вас нет клеинтов использующих его напрямую? Я имею в виду необходимость сопровождения, customization.

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

                                                                                                                Самое читаемое