
Quero poder monitorar o número de arquivos abertos no Linux. Atualmente estou contando o número de arquivos em /proc/<pid>/fd
e fdinfo
.
Meu balanceador de carga tem cerca de um milhão de FDs. Então isso acaba levando cerca de 20 segundos para ser executado.
No entanto, isso resulta em alto uso da CPU:47.18% [kernel] [k] __d_lookup
Existe uma maneira mais eficiente de obter esse número?
Responder1
Para um balanceador de carga dedicado, eu rastrearia o total de arquivos abertos no sistema, em vez de desperdiçar recursos de E/S e CPU contando-os por processo. Os arquivos abertos restantes por processos indesejados devem ser um valor sem sentido para o resultado pretendido.
Para conhecer os arquivos globais abertos pelo sistema Linux, não há necessidade de contá-los; o kernel do Linux monitora quantos arquivos estão abertos.
Para saber isso, execute:
cat /proc/sys/fs/file-nr | awk ' { print $1 } '
ou
sysctl fs.file-nr | awk ' { print $1 } '
Isso é muito mais eficiente do que contar todos os arquivos abertos com a saída de lsof
, que percorrerá todos /proc/$PID/fd
os diretórios e afetará negativamente os recursos de E/S/CPU do sistema.
Responder2
O simples:
lsof | wc -l
informará o número de arquivos abertos no sistema.
Responder3
Quão eficiente é esse código SystemTap para o seu caso de uso? Não é uma visualização perfeita, pois apenas rastreia as alterações desde o início (portanto, qualquer coisa aberta antes do início seria perdida) e precisará de trabalho adicional para tornar a saída mais legível ou adequada.
global procfdcount
probe begin {
printf("begin trace...\n\n")
}
probe syscall.open {
procfdcount[pid()]++
}
probe syscall.close {
p = pid()
procfdcount[p]--
if (procfdcount[p] < 0) {
procfdcount[p] = 0
}
}
probe kprocess.exit {
p = pid()
if (p in procfdcount) {
delete procfdcount[p]
}
}
probe timer.s(60) {
foreach (p in procfdcount- limit 20) {
printf("%d %lu\n", p, procfdcount[p])
}
printf("\n")
}
Execute algo como:
... (install systemtap here) ...
# stap-prep
... (fix any reported systemtap issues here) ...
# stap procfdcount.stp
A desvantagem deste método é a necessidade de identificar todos os "arquivos abertos" (soquetes, etc.) e então ajustar a contagem através de ganchos de chamada de sistema apropriados (se disponíveis); o acima apenas rastreia arquivos de arquivo. Outra opção seria solicitar task_open_file_handles
tarefas que chegam à CPU e exibir periodicamente as contagens mais recentes.
global taskopenfh
probe begin {
printf("begin trace...\n\n");
}
probe scheduler.cpu_on {
p = pid();
if (p == 0) next;
taskopenfh[p] = task_open_file_handles(pid2task(p));
}
probe timer.s(60) {
foreach (p in taskopenfh-) {
printf("%d %lu\n", p, taskopenfh[p]);
}
delete taskopenfh;
printf("\n");
}
No entanto, isso perderia qualquer coisa que não estivesse na CPU; uma caminhada completa pelos processos e tarefas seria necessária para uma lista completa, embora isso possa ser muito lento ou muito caro se você tiver milhões de FDs.
Além disso, essas sondas não parecem estáveis, então talvez eBPF ou algo assim no futuro? Por exemplo, o segundo no Centos 7 explode depois de algum tempo ligado
ERROR: read fault [man error::fault] at 0x0000000000000008 (((&(fs->fdt))))
near identifier 'task_open_file_handles' at
/usr/share/systemtap/tapset/linux/task.stp:602:10