CoreCLR usa mlock
durante el inicio y falla si mlock
falla con EPERM
. Generalmente, eso no es un problema.
Sin embargo, muchas distribuciones de Linux están comenzando a usar systemd-nspawn
para crear código. Esto crea un chroot donde los programas tienen capacidades restringidas. Específicamente, no tienen CAP_IPC_LOCK
, lo que significa que no pueden usar mlock
.
Cuando mlock
no funciona, coreclr no se inicia. Esto aparece en un strace
como algo como:
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
Como resultado, esto hace que sea básicamente imposible compilar coreclr en algunos sistemas de compilación de distribución de Linux.
cc @tmds @alucryd
Consulte https://github.com/dotnet/source-build/issues/285#issuecomment -399949984 y https://github.com/rpm-software-management/mock/issues/186 para ver algunos ejemplos en los que esto afecta a algunos construye
El mlock
es necesario para el correcto funcionamiento de la función PAL FlushProcessWriteBuffers que es crucial para garantizar una suspensión confiable del tiempo de ejecución para GC. Consulte https://github.com/dotnet/coreclr/blob/e6ebea25bea93eb4ec07cbd5003545c4805886a8/src/pal/src/thread/process.cpp#L3095 -L3098 para obtener una descripción del motivo.
En Linux 4.3 y versiones posteriores, hay una llamada al sistema sys_membarrier
que podríamos usar como mecanismo alternativo para implementar FlushProcessWriteBuffers. El problema dotnet/runtime#4501 está rastreando eso. @sdmaclea intentó implementarlo y lo probó en ARM64. Descubrió que el rendimiento era realmente malo y que el tiempo de ejecución de nuestras pruebas de ~11000 coreclr era aproximadamente un 50 % más largo. Sin embargo, no se realizaron pruebas en otro hardware, por lo que no quedó claro si el problema de rendimiento es específico de ARM64 o es un problema general.
Curiosamente, acabo de descubrir el siguiente artículo que describe problemas de rendimiento con sys_membarrier: https://lttng.org/blog/2018/01/15/membarrier-system-call-performance-and-userspace-rcu/. La razón es que la llamada al sistema espera internamente hasta que todos los subprocesos en ejecución en el sistema hayan pasado por un cambio de contexto, lo que podría demorar decenas de milisegundos. Pero la buena noticia mencionada en este artículo es que, a partir de Linux 4.14, hay un nuevo indicador que se puede pasar a la llamada al sistema sys_membarrier y que hace que use IPI para implementar la semántica de barrera de memoria. Y eso es mucho más rápido. Así que deberíamos darle una oportunidad.
Comentario más útil
El
mlock
es necesario para el correcto funcionamiento de la función PAL FlushProcessWriteBuffers que es crucial para garantizar una suspensión confiable del tiempo de ejecución para GC. Consulte https://github.com/dotnet/coreclr/blob/e6ebea25bea93eb4ec07cbd5003545c4805886a8/src/pal/src/thread/process.cpp#L3095 -L3098 para obtener una descripción del motivo.En Linux 4.3 y versiones posteriores, hay una llamada al sistema
sys_membarrier
que podríamos usar como mecanismo alternativo para implementar FlushProcessWriteBuffers. El problema dotnet/runtime#4501 está rastreando eso. @sdmaclea intentó implementarlo y lo probó en ARM64. Descubrió que el rendimiento era realmente malo y que el tiempo de ejecución de nuestras pruebas de ~11000 coreclr era aproximadamente un 50 % más largo. Sin embargo, no se realizaron pruebas en otro hardware, por lo que no quedó claro si el problema de rendimiento es específico de ARM64 o es un problema general.Curiosamente, acabo de descubrir el siguiente artículo que describe problemas de rendimiento con sys_membarrier: https://lttng.org/blog/2018/01/15/membarrier-system-call-performance-and-userspace-rcu/. La razón es que la llamada al sistema espera internamente hasta que todos los subprocesos en ejecución en el sistema hayan pasado por un cambio de contexto, lo que podría demorar decenas de milisegundos. Pero la buena noticia mencionada en este artículo es que, a partir de Linux 4.14, hay un nuevo indicador que se puede pasar a la llamada al sistema sys_membarrier y que hace que use IPI para implementar la semántica de barrera de memoria. Y eso es mucho más rápido. Así que deberíamos darle una oportunidad.