Взаимодействие с другими процессами
В Linux исторически у одного процесса мало способов взаимодействовать на другие процессы после их создания. Все эти годы существовала только отправка сигналов и ptrace(). Оно не зря продержалось долгое время, -- не стоит миксовать абстракции, пока нет устоявшихся временем понятий и понимания, что ничего не поменяется в перспективе.
В последние годы в сообществе Linux увеличился сильный интерес к предоставлению процессам способов управления другими или обеспечения чуть больше контроля даже за структурами внутри. Скажем, для userfaultfd(2), который разрешает делать абсолютную грязь с pagefault в юзерспейсе, я могу придумать с десяток различных сценариев, что можно делать интересного с памятью -- сжимать, находить паттерны, следить за качеством и количеством, собирать статистику и прочее.
Не так давно (в Linux 5.13) наконец-то приняли в Linux системный process_madvise(). Эта история интересна сама по себе, в Linux разрешили управлять (ладно, не управлять, а "советовать") страницами памяти других процессов. Сделали изначалально достаточно консервативно. С другой стороны, удовлетворяют интересам сообщества Linux.
madvise(2) сам по себе предоставляет механизмы работы с памятью, когда можно посылать "советы" тем или иным страницам. В самом madvise(2) в Linux 5.4 добавили две опции MADV_COLD и MADV_PAGEOUT. Первая просит ядро поместить указанный диапазон страниц в "inactive list", говоря, что они давно не использовались. Эти страницы будут первыми для рассмотрения на вытаскивание, если ядру потребуется память для других целей. MADV_PAGEOUT является более сильным советом о том, что указанные страницы больше не нужны. Это приводит к их немедленной рекламации.
Чтобы осуществлять такие махинации, process_madvise(2) взял эти две опции и начал использовать вместе с недавним механизмом в ядре под названием pidfd_open(2), где нам c Linux 5.3 теперь можно работать с процессами как с файловыми дескрипторами. Теперь вам дают файловый дескриптор и можно с ним взаимодействовать. API у process_madvise(2) получается правильным, всё советую делать в OS через файловые дескрипторы.
Стоит отметить, что совсем недавно (Август 2021) process_madvise(2) добавил опцию MADV_WILLNEED, которая говорит, что скоро память понадобится процессу. Такой механизм отлично работает, если процесс стал проявлять активность, и хочется сделать prefetch всей остальной памяти.
Зачем это надо?
В очень разносторонних окружениях таких как серверы или телефоны, этим можно начинать пользоваться.
Скажем, Android начал использовать process_madvise для оптимизации памяти приложений, которые уходят в background. Вы выходите из chrome или spotify, вряд ли вы туда быстро вернётесь, можно память вытеснить на что-то более полезное. А как только начнёте пользоваться, можно сделать prefetch всей остальной памяти. В итоге лучше управление, быстрее говорим памяти, что делать, больше освобождаем место тому, кому это надо.
Если что, компакция памяти и такие оптимизации делаются уже в Android 12, и фиксы с оптимизациями оверхеда, чтобы это работало ещё шустрее происходят прям на этой неделе.
Это также может быть полезно serverless базам данных, скажем, по запросу мы можем угадать, какие паттерны памяти будут использоваться теми или иными хостами, но тут, конечно, надо изобрести что-то интересное.
Более простой пример, который приходит на ум -- попытаться сделать глобальный аллокатор на сервере, который рассуждает сам, кто просыпается, а кто засыпает, чтобы контролировать паттерны памяти.
Ещё, надеюсь, с развитием других опций, мы сможем применить MADV_DONTDUMP, которая говорит, что не надо в coredump страницы выкладывать и, если мы обрабатываем пользовательские данные или секреты, то их можно пометить таким флагом. И это может быть cloud решение, а не каждая программа сама писать.
Интересно очень, прям хоть начинай эпоху глобальных оптимизаторов памяти для хостов.
[1] process_madvise(2), madvise(2)
[2] pidfd_open(2)
[3] Оптимизации памяти Android с помощью process_madvise и ускорение
В Linux исторически у одного процесса мало способов взаимодействовать на другие процессы после их создания. Все эти годы существовала только отправка сигналов и ptrace(). Оно не зря продержалось долгое время, -- не стоит миксовать абстракции, пока нет устоявшихся временем понятий и понимания, что ничего не поменяется в перспективе.
В последние годы в сообществе Linux увеличился сильный интерес к предоставлению процессам способов управления другими или обеспечения чуть больше контроля даже за структурами внутри. Скажем, для userfaultfd(2), который разрешает делать абсолютную грязь с pagefault в юзерспейсе, я могу придумать с десяток различных сценариев, что можно делать интересного с памятью -- сжимать, находить паттерны, следить за качеством и количеством, собирать статистику и прочее.
Не так давно (в Linux 5.13) наконец-то приняли в Linux системный process_madvise(). Эта история интересна сама по себе, в Linux разрешили управлять (ладно, не управлять, а "советовать") страницами памяти других процессов. Сделали изначалально достаточно консервативно. С другой стороны, удовлетворяют интересам сообщества Linux.
madvise(2) сам по себе предоставляет механизмы работы с памятью, когда можно посылать "советы" тем или иным страницам. В самом madvise(2) в Linux 5.4 добавили две опции MADV_COLD и MADV_PAGEOUT. Первая просит ядро поместить указанный диапазон страниц в "inactive list", говоря, что они давно не использовались. Эти страницы будут первыми для рассмотрения на вытаскивание, если ядру потребуется память для других целей. MADV_PAGEOUT является более сильным советом о том, что указанные страницы больше не нужны. Это приводит к их немедленной рекламации.
Чтобы осуществлять такие махинации, process_madvise(2) взял эти две опции и начал использовать вместе с недавним механизмом в ядре под названием pidfd_open(2), где нам c Linux 5.3 теперь можно работать с процессами как с файловыми дескрипторами. Теперь вам дают файловый дескриптор и можно с ним взаимодействовать. API у process_madvise(2) получается правильным, всё советую делать в OS через файловые дескрипторы.
Стоит отметить, что совсем недавно (Август 2021) process_madvise(2) добавил опцию MADV_WILLNEED, которая говорит, что скоро память понадобится процессу. Такой механизм отлично работает, если процесс стал проявлять активность, и хочется сделать prefetch всей остальной памяти.
Зачем это надо?
В очень разносторонних окружениях таких как серверы или телефоны, этим можно начинать пользоваться.
Скажем, Android начал использовать process_madvise для оптимизации памяти приложений, которые уходят в background. Вы выходите из chrome или spotify, вряд ли вы туда быстро вернётесь, можно память вытеснить на что-то более полезное. А как только начнёте пользоваться, можно сделать prefetch всей остальной памяти. В итоге лучше управление, быстрее говорим памяти, что делать, больше освобождаем место тому, кому это надо.
Если что, компакция памяти и такие оптимизации делаются уже в Android 12, и фиксы с оптимизациями оверхеда, чтобы это работало ещё шустрее происходят прям на этой неделе.
Это также может быть полезно serverless базам данных, скажем, по запросу мы можем угадать, какие паттерны памяти будут использоваться теми или иными хостами, но тут, конечно, надо изобрести что-то интересное.
Более простой пример, который приходит на ум -- попытаться сделать глобальный аллокатор на сервере, который рассуждает сам, кто просыпается, а кто засыпает, чтобы контролировать паттерны памяти.
Ещё, надеюсь, с развитием других опций, мы сможем применить MADV_DONTDUMP, которая говорит, что не надо в coredump страницы выкладывать и, если мы обрабатываем пользовательские данные или секреты, то их можно пометить таким флагом. И это может быть cloud решение, а не каждая программа сама писать.
Интересно очень, прям хоть начинай эпоху глобальных оптимизаторов памяти для хостов.
[1] process_madvise(2), madvise(2)
[2] pidfd_open(2)
[3] Оптимизации памяти Android с помощью process_madvise и ускорение