Прежде всего большое спасибо за статью. Очень интересно и вдохновляюще. Решил после неё поэкспериментировать над нашим CI. Суть в том, что там крутится много разных задач, которые пересобирают в разных вариантах одни и те же исходники. В результате получается огромное дублирование данных. В ближаёшее время надо будет увеличить количество задач и количество обрабатываемых исходников. Как следствие нужно или значительно расширять дисковое пространство или как-то дедублицировать данные на диске.
Дай, думаю, попробую дедубликацию ZFS:
Взял виртуалку на нашем proxmox. Отрезал для тестов 100G том, создал пул:
Ну я ничего не указывал специально. Кеш в некоторые моменты отъедает половину оперативки. Но если я в этот момент запускаю локально приложение с прода, которое заведомо съедает всю память, то ничего летального не происходит. Кеш отдаёт память этому приложению. Ну обмен с диском начинает ожидаемо тупить. Но он и так тупил в этом случае. Ещё до установки zfs. Сейчас мне даже кажется, что после остановки приложения система быстрее вылазит из тупежей. Но конкретных замеров не делал.
У меня в таких условиях полёт нормальный. Только надо учитывать, что ARC кеш выглядит так, как будто какое-то приложение сожрало всю память. Хотя реально эта память свободно перераспределяется под нужды приложений по требованию. Короче в моём случае работает, хоть и выглядит странно.
Использую для тестирования приложений на больших БД, которые надо долго готовить для каждого прогона. А так пересоздал снапшот и готово. Очень доволен.
Ну вот в том-то и вопрос, что активация на постоянной основе спотыкается об требование памяти. Но одноразовые прогоны дедубликации по уже записанным данным может решить большинство ситуаций. Но этого как раз и не предусмотрено. Увы...
А рассматривается ли возможность ручного прогона дедубликации в отведённый даунтайм без необходимости включать его напостоянно? Есть один юзкейс (CI/DI сервера) когда происходит сильное дублирование данных и можно было бы по выходным прогонять дедубликатор (когда всё стоит и можно испоьзовать хоть всю память для этого). Но постоянно гонять никак т.к. память для работы нужна.
Очень может быть что я и ошибаюсь. Тем не менее я довольно давно слежу за развитием языка. И помню когда появилось ключевое слово inline и какой аргументацией сопровождалось его почвление. Reified, android и т.п. появились позже. Как развитие удачной идеи. Ну и JVM на месте не стоит. Возможно мой опыт устарел. Надо будет освежить.
Что-то не могу найти так сразу ссылку на пруф, но как раз при обсуждении inline с разработчиками Kotlin я и узнал, что ели передать лямбду как параметр метода, то тело метода заинлайнено может быть, а вот тело лямбды уже нет.
Inline Котлина же позволяет явно заинлайнить и тело метода и тело лямбды, которая туда была передана.
Ну а уже потом и reified туда наверну, превратив inkine вообще в киллер фичу.
inline в Kotlin сделан не от хорошей жизни, а потому, что JIT не умеет инлайнить лямбды, переданные по параметру. Это своего рода обход известного ограничения JIT. Из статьи же создается впечатления, что разработчики языка недоверяют стандартному инлайнингу. Вполне доверяют, но хотят большего.
Ну тут как сказать… У меня на практике был случай когда одно лишнее обращение к полю класса ломало длинную цепочку оптимизаций JIT и производительность проседала вдвое. Так что моё личное мнение таково, что библиотеки ядра системы должны быть максимально оптимизированными, т.к. никогда не знаешь где и как они будут использоваться.
В этом свете удивляют комментарии некоторых разработчиков, мол тут мы оставим так, потому что JIT потом всё вычистит. Ага… Где-то вычистит а где-то и подавится. Т.к. эффект на оптимизации в подавляющем большинстве случаев нелокален.
Софт — да проблема. И да, насколько она велика конкретно у вас мне не известно. Ну как показывает хоть и скромная, но практика, если внимательно посмотреть инфраструктуру, то оказывается:
что такой софт нужен не всем
чем меньше пользователь компетентен — тем меньше у него шансов наступить на грабли. Особенно на предприятии. Где список необходимого софта строго регламентирован.
психологический барьер существует не в головах переводимых, а в голове переводящих.
Вообще если приложение запускается на сервере, то -Xmx должен быть задан в обязательном порядке. Ограничение на metaspace тоже желательно задавать. Другие ограничения по расходу памяти в OpenJDK так же присутствуют (для буферо машинного кода jit, offheap память и т.д.). Но если это все задавать, то какой смысл дублировать это через докер?
Какой-то странный когнитивный диссонанс возник по ходу рассказа. С одной стороны m0nstermind говорит, что они очень внимательно относятся к распределению знаний между людьми для исключения фактора трамвая, а с другой — выясняется, что тот-же one-nio нормально знает только apangin и для толкового документирования этой библиотеки нужно очень серёзно отвлекать автора. И тут же вопрос:"А зачем нам тратиться на оформления OpenSourse проекта?"
Не знаю как на счёт конкретно OpenSourse, но в целом подобного рода работа даже просто на уровне компании как раз и гарантирует качественное распределение знаний между сотрудниками. Т.к. если сторонний человек таки написал, например, документацию к проекту и у автора библиотеки не возникло к итоговому варианту претензий, то это значит что человек уже разобрался в проекте достаточно хорошо. Да автора отвлекать придётся. Но как ещё знания-то передавать?
А если ещё и по коду прилизать что-то корректно смог, то по поводу трамвая уже можно не так сильно париться :-)
А вот уже от OpenSourse можно получить бонус в другом плане: при поиске специалистов для найма. Если человек воспользовался библиотекой такого уровня в своём проекте и сделал это корректно, то он уже может являться хорошим кандидатом для привлечения в компанию. Возможно выхлоп от такого подхода будет ничуть не хуже, чем от организации конференций ;-)
P.S. Всё это чисто мои умозаключения. Возможно ложные.
P.P.S. Надеюсь не очень путано изложил свои мысли.
К стати, если делать дамп таким макаром, то там ещё и информация о потоках сохраняется, Это позволяет сразу переходить к списку потоков (большая жёлтая шестерёнка на скриншоте MAT) и смотреть какой поток сколько памяти удерживает и почему. Сокращает время поиска причины утечки памяти буквально до нескольких минут.
Буквально вот только что очередной дамп расковырял. Основное время ушло на перекачку дампа к себе на комп и его индексирование. Далее буквально за пару минут виноватого нашёл.
Описано как снимать дапм памяти максимально быстро (в случае если надо снять дамп на проде и нужно минимизировать время простоя). Фактически, при таком способе, скорость создания дампа ограничена только скоростью дисковой подсистемы, что на нормальных серверах весьма приятно.
Результат спокойно открывается в современной версии MAT без предварительных преобразований. Главное чтобы версия JVM совпадала с версией с которой дамп снимался.
Прежде всего большое спасибо за статью. Очень интересно и вдохновляюще. Решил после неё поэкспериментировать над нашим CI. Суть в том, что там крутится много разных задач, которые пересобирают в разных вариантах одни и те же исходники. В результате получается огромное дублирование данных. В ближаёшее время надо будет увеличить количество задач и количество обрабатываемых исходников. Как следствие нужно или значительно расширять дисковое пространство или как-то дедублицировать данные на диске.
Дай, думаю, попробую дедубликацию ZFS:
Взял виртуалку на нашем proxmox. Отрезал для тестов 100G том, создал пул:
Оперативки выдал 24G.
Сначала вроде всё полетело нормально, но потом начал замечать, что периодически ZFS уходит в жирный IO wait, останавливая все процессы.
По расчётам процессы не должны выедать больше 6-8G памяти.
То-ли под ARC памяти не хватает, то-ли чего… Пока опыт небольшой — не могу понять как это корректно диагностировать и куда смотреть.
Буду рад любой помощи.
Ну я ничего не указывал специально. Кеш в некоторые моменты отъедает половину оперативки. Но если я в этот момент запускаю локально приложение с прода, которое заведомо съедает всю память, то ничего летального не происходит. Кеш отдаёт память этому приложению. Ну обмен с диском начинает ожидаемо тупить. Но он и так тупил в этом случае. Ещё до установки zfs. Сейчас мне даже кажется, что после остановки приложения система быстрее вылазит из тупежей. Но конкретных замеров не делал.
Или я где-то не прав?
У меня в таких условиях полёт нормальный. Только надо учитывать, что ARC кеш выглядит так, как будто какое-то приложение сожрало всю память. Хотя реально эта память свободно перераспределяется под нужды приложений по требованию. Короче в моём случае работает, хоть и выглядит странно.
Использую для тестирования приложений на больших БД, которые надо долго готовить для каждого прогона. А так пересоздал снапшот и готово. Очень доволен.
Ну вот в том-то и вопрос, что активация на постоянной основе спотыкается об требование памяти. Но одноразовые прогоны дедубликации по уже записанным данным может решить большинство ситуаций. Но этого как раз и не предусмотрено. Увы...
А рассматривается ли возможность ручного прогона дедубликации в отведённый даунтайм без необходимости включать его напостоянно? Есть один юзкейс (CI/DI сервера) когда происходит сильное дублирование данных и можно было бы по выходным прогонять дедубликатор (когда всё стоит и можно испоьзовать хоть всю память для этого). Но постоянно гонять никак т.к. память для работы нужна.
Очень может быть что я и ошибаюсь. Тем не менее я довольно давно слежу за развитием языка. И помню когда появилось ключевое слово inline и какой аргументацией сопровождалось его почвление. Reified, android и т.п. появились позже. Как развитие удачной идеи. Ну и JVM на месте не стоит. Возможно мой опыт устарел. Надо будет освежить.
Промахнулся веткой. Ответил ниже.
Что-то не могу найти так сразу ссылку на пруф, но как раз при обсуждении inline с разработчиками Kotlin я и узнал, что ели передать лямбду как параметр метода, то тело метода заинлайнено может быть, а вот тело лямбды уже нет.
Inline Котлина же позволяет явно заинлайнить и тело метода и тело лямбды, которая туда была передана.
Ну а уже потом и reified туда наверну, превратив inkine вообще в киллер фичу.
inline в Kotlin сделан не от хорошей жизни, а потому, что JIT не умеет инлайнить лямбды, переданные по параметру. Это своего рода обход известного ограничения JIT. Из статьи же создается впечатления, что разработчики языка недоверяют стандартному инлайнингу. Вполне доверяют, но хотят большего.
Ну это было достаточно давно и в закрытом коде. Увы. Но и без меня много кто про это рассказывает. Вот, рекомендую:
Ну тут как сказать… У меня на практике был случай когда одно лишнее обращение к полю класса ломало длинную цепочку оптимизаций JIT и производительность проседала вдвое. Так что моё личное мнение таково, что библиотеки ядра системы должны быть максимально оптимизированными, т.к. никогда не знаешь где и как они будут использоваться.
В этом свете удивляют комментарии некоторых разработчиков, мол тут мы оставим так, потому что JIT потом всё вычистит. Ага… Где-то вычистит а где-то и подавится. Т.к. эффект на оптимизации в подавляющем большинстве случаев нелокален.
Софт — да проблема. И да, насколько она велика конкретно у вас мне не известно. Ну как показывает хоть и скромная, но практика, если внимательно посмотреть инфраструктуру, то оказывается:
Впрочем согласен, что везде по разному...
Ну либо вам повезёт, либо вот он шанс...
Вообще если приложение запускается на сервере, то -Xmx должен быть задан в обязательном порядке. Ограничение на metaspace тоже желательно задавать. Другие ограничения по расходу памяти в OpenJDK так же присутствуют (для буферо машинного кода jit, offheap память и т.д.). Но если это все задавать, то какой смысл дублировать это через докер?
А в этот раз какие-то вечеринки намечаются или можно планировать досуг на своё усмотрение?
Какой-то странный когнитивный диссонанс возник по ходу рассказа. С одной стороны m0nstermind говорит, что они очень внимательно относятся к распределению знаний между людьми для исключения фактора трамвая, а с другой — выясняется, что тот-же one-nio нормально знает только apangin и для толкового документирования этой библиотеки нужно очень серёзно отвлекать автора. И тут же вопрос:"А зачем нам тратиться на оформления OpenSourse проекта?"
Не знаю как на счёт конкретно OpenSourse, но в целом подобного рода работа даже просто на уровне компании как раз и гарантирует качественное распределение знаний между сотрудниками. Т.к. если сторонний человек таки написал, например, документацию к проекту и у автора библиотеки не возникло к итоговому варианту претензий, то это значит что человек уже разобрался в проекте достаточно хорошо. Да автора отвлекать придётся. Но как ещё знания-то передавать?
А если ещё и по коду прилизать что-то корректно смог, то по поводу трамвая уже можно не так сильно париться :-)
А вот уже от OpenSourse можно получить бонус в другом плане: при поиске специалистов для найма. Если человек воспользовался библиотекой такого уровня в своём проекте и сделал это корректно, то он уже может являться хорошим кандидатом для привлечения в компанию. Возможно выхлоп от такого подхода будет ничуть не хуже, чем от организации конференций ;-)
P.S. Всё это чисто мои умозаключения. Возможно ложные.
P.P.S. Надеюсь не очень путано изложил свои мысли.
К стати, если делать дамп таким макаром, то там ещё и информация о потоках сохраняется, Это позволяет сразу переходить к списку потоков (большая жёлтая шестерёнка на скриншоте MAT) и смотреть какой поток сколько памяти удерживает и почему. Сокращает время поиска причины утечки памяти буквально до нескольких минут.
Буквально вот только что очередной дамп расковырял. Основное время ушло на перекачку дампа к себе на комп и его индексирование. Далее буквально за пару минут виноватого нашёл.
Ну как вариант. Но вот копипастить оттуда примеры несколько проблематичнее...
Книга отличная. Спасибо. Но в главе "Полезные мелочи" все примеры проглочены. Хотя в исходниках они вроде как есть.
Ещё полезная ссылка: http://blogs.atlassian.com/2013/03/so-you-want-your-jvms-heap/
Описано как снимать дапм памяти максимально быстро (в случае если надо снять дамп на проде и нужно минимизировать время простоя). Фактически, при таком способе, скорость создания дампа ограничена только скоростью дисковой подсистемы, что на нормальных серверах весьма приятно.
Результат спокойно открывается в современной версии MAT без предварительных преобразований. Главное чтобы версия JVM совпадала с версией с которой дамп снимался.