Runtime: CoreCLR не запускается, когда mlock недоступен

Созданный на 25 июн. 2018  ·  3Комментарии  ·  Источник: dotnet/runtime

CoreCLR использует mlock во время запуска и дает сбой, если mlock завершается сбоем с EPERM . Как правило, это не проблема.

Однако многие дистрибутивы Linux начинают использовать systemd-nspawn для сборки кода. Это создает chroot, в котором программы имеют ограниченные возможности. В частности, у них нет CAP_IPC_LOCK , что означает, что они не могут использовать mlock .

Когда mlock не работает, coreclr не запускается. Это отображается в strace как что-то вроде:

mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7fbd542bb000
mlock(0x7fbd542bb000, 4096)       = -1 EPERM (Operation not permitted)
write(2, "Failed to initialize CoreCLR, HR"..., 49) = 49

В результате это делает практически невозможным сборку coreclr в некоторых системах сборки дистрибутива Linux.

area-PAL-coreclr os-linux

Самый полезный комментарий

mlock необходим для правильного поведения функции FlushProcessWriteBuffers PAL, которая имеет решающее значение для обеспечения надежной приостановки выполнения сборщика мусора. См. https://github.com/dotnet/coreclr/blob/e6ebea25bea93eb4ec07cbd5003545c4805886a8/src/pal/src/thread/process.cpp#L3095 -L3098 для описания причины.
В Linux 4.3 и выше есть системный вызов sys_membarrier , который мы могли бы использовать в качестве альтернативного механизма для реализации FlushProcessWriteBuffers. Проблема dotnet/runtime#4501 отслеживает это. @sdmaclea попытался реализовать это и протестировал на ARM64. Он обнаружил, что производительность была очень плохой, а время выполнения наших ~11000 тестов coreclr было примерно на 50% больше. Однако тестирование на другом оборудовании не проводилось, поэтому неясно, связана ли проблема с производительностью с ARM64 или с общей проблемой.
Интересно, что я только что обнаружил следующую статью, описывающую проблемы производительности с sys_membarrier: https://lttng.org/blog/2018/01/15/membarrier-system-call-performance-and-userspace-rcu/. Причина в том, что системный вызов внутренне ожидает, пока все запущенные потоки в системе не пройдут через переключение контекста, что может занять десятки миллисекунд. Но хорошая новость, упомянутая в этой статье, заключается в том, что, начиная с Linux 4.14, появился новый флаг, который можно передать системному вызову sys_membarrier и который позволяет использовать IPI для реализации семантики барьера памяти. А это гораздо быстрее. Так что мы должны попробовать.

Все 3 Комментарий

копия @tmds @alucryd

См. https://github.com/dotnet/source-build/issues/285#issuecomment -399949984 и https://github.com/rpm-software-management/mock/issues/186 для некоторых примеров, когда это поражает некоторые строит

mlock необходим для правильного поведения функции FlushProcessWriteBuffers PAL, которая имеет решающее значение для обеспечения надежной приостановки выполнения сборщика мусора. См. https://github.com/dotnet/coreclr/blob/e6ebea25bea93eb4ec07cbd5003545c4805886a8/src/pal/src/thread/process.cpp#L3095 -L3098 для описания причины.
В Linux 4.3 и выше есть системный вызов sys_membarrier , который мы могли бы использовать в качестве альтернативного механизма для реализации FlushProcessWriteBuffers. Проблема dotnet/runtime#4501 отслеживает это. @sdmaclea попытался реализовать это и протестировал на ARM64. Он обнаружил, что производительность была очень плохой, а время выполнения наших ~11000 тестов coreclr было примерно на 50% больше. Однако тестирование на другом оборудовании не проводилось, поэтому неясно, связана ли проблема с производительностью с ARM64 или с общей проблемой.
Интересно, что я только что обнаружил следующую статью, описывающую проблемы производительности с sys_membarrier: https://lttng.org/blog/2018/01/15/membarrier-system-call-performance-and-userspace-rcu/. Причина в том, что системный вызов внутренне ожидает, пока все запущенные потоки в системе не пройдут через переключение контекста, что может занять десятки миллисекунд. Но хорошая новость, упомянутая в этой статье, заключается в том, что, начиная с Linux 4.14, появился новый флаг, который можно передать системному вызову sys_membarrier и который позволяет использовать IPI для реализации семантики барьера памяти. А это гораздо быстрее. Так что мы должны попробовать.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги