Sempre que se trata de comunicação entre processos, a memória compartilhada parece ser a maneira mais rápida de fazê-lo. Uma vez que a memória é mapeada no espaço de endereço na região da memória, nenhum envolvimento adicional do kernel é necessário. Fantástico! Porque, ao contrário de outros métodos (FIFO, mensagens), você subverte as chamadas do sistema, o que o torna extremamente rápido.
Estaremos passando por alguns fundamentos de mmap (mapeamento de memória) usando Python. Felizmente, o python tem um módulo embutido chamado mmap que expõe a maioria das chamadas usando api.
Tenho um arquivo de amostra pgm1.go que contém um programa go simples (não se preocupe, não vou entrar na linguagem de programação go). Estamos apenas mapeando o conteúdo do arquivo na memória e lendo seu conteúdo.
import mmap
with open('pgm1.go', 'r+b') as f:
mm = mmap.mmap(f.fileno(),0)
for i in mm:
print mm.readline()
Agora, como verificamos se os dados estão realmente na memória. É aqui que a ferramenta pmap é muito útil. Mas espere um segundo! , não temos isso no OS X, temos? Pelo menos não estou ciente disso. Felizmente o OS X vem com o vmmap, que exibe lindamente as mesmas informações.
besidecome-lm:pointers rahulram$ vmmap 71058
==== Summary for process 71058
ReadOnly portion of Libraries: Total=57.9M resident=16.4M(28%) swapped_out_or_unallocated=41.5M(72%)
Writable regions: Total=19.9M written=1936K(10%) resident=2556K(13%) swapped_out=0K(0%) unallocated=17.4M(87%)
REGION TYPE VIRTUAL
=========== =======
MALLOC 11.2M see MALLOC ZONE table below
MALLOC guard page 32K
MALLOC metadata 356K
STACK GUARD 56.0M
Stack 8192K
__DATA 1296K
__LINKEDIT 47.8M
__TEXT 10.0M
__UNICODE 544K
mapped file 4K
shared memory 8K
=========== =======
TOTAL 135.2M
Lá você vê que o arquivo mapeado é mostrado como sendo de tamanho 4K. Em seu interpretador python, você pode
mm.close ()
e ver que o vmmap não lista essa informação. Sim, eu confio no vmmap e o considero garantido: P
Vamos dar outro exemplo envolvendo vários processos
import mmap
import os
with open('pgm1.go', 'r+b') as f:
mm = mmap.mmap(f.fileno(),0)
print os.getpid()
pid = os.fork() # Creating a child process
if pid == 0:
mm.seek(0)
print os.getpid()
print os.getppid()
print mm.readline()
mm.close()
O processo filho é basicamente ler o conteúdo do mmap e fechar o mesmo.
Nota: se o objeto mm for fechado antes que outros processos o estejam usando, ele começará a lançar uma exceção. Certifique-se de que o objeto mm esteja fechado somente após liberar o conteúdo para o disco