2015-02-17 8 views
10

Mam proces Pythona służący jako serwer WSGI-apache. Mam wiele kopii tego procesu uruchomionych na każdym z kilku komputerów. Około 200 megabajtów mojego procesu to dane pythonowe tylko do odczytu. Chciałbym umieścić te dane w segmencie mapowanym w pamięci, aby procesy mogły współdzielić jedną kopię tych danych. Najlepiej byłoby móc dołączyć do tych danych, aby mogły być rzeczywistymi obiektami danych python 2.7, a nie analizować je z czegoś takiego jak pikle lub DBM lub SQLite.Jak przechowywać łatwo Pythona użyteczne struktury danych tylko do odczytu w pamięci wspólnej

Czy ktoś ma przykładowy kod lub wskaźniki do projektu, który zrobił to, aby udostępnić?

+0

"Około 200 megabajtów mojego procesu to dane pythonowe tylko do odczytu." Nie mogłem zrozumieć tej części. Czy możesz podać trochę szczegółów? Jaki rodzaj danych? Co próbowałeś? –

+1

Jakiego systemu operacyjnego używasz i jak się rozwidlają twoje procesy?Jeśli używasz 'vfork', to dziecko udostępnia kopię stron swoich rodziców, dopóki i tak nie napisze do nich. –

+0

Dlaczego korzystanie z usługi Redis nie rozwiązałoby problemu? –

Odpowiedz

1

Ponieważ jest to dane tylko do odczytu, nie będzie potrzeby udostępniania żadnych aktualizacji między procesami (ponieważ nie będzie żadnych aktualizacji), proponuję zachować lokalną kopię tego procesu w każdym procesie.

Jeśli ograniczenia pamięci jest problem można spojrzeć na użyciu multiprocessing.Value lub multiprocessing.Array bez zamków na to: https://docs.python.org/2/library/multiprocessing.html#shared-ctypes-objects

Poza tym będziesz musiał polegać na proces zewnętrznego, a niektóre SZEREGOWANIE aby to zrobić , Gdybym był tobą, rzuciłbym okiem na Redisa lub Memcached.

3

This post przez @modelnine na StackOverflow zapewnia naprawdę doskonałą kompleksową odpowiedź na to pytanie. Jak wspomniał, używanie wątków zamiast rozwidlania procesów na serwerze może znacznie obniżyć ich wpływ. I ran into a similar problem trying to share extremely-large NumPy arrays między procesami CLI w Pythonie korzystającym z pewnego rodzaju pamięci współdzielonej sprzed kilku lat, a ostatecznie wykorzystaliśmy kombinację rozszerzenia Python sharedmem do udostępniania danych między pracownikami (co okazało się nieszczelne w niektórych przypadkach, ale można je naprawić prawdopodobnie). Technika tylko do odczytu mmap() może ci pomóc, ale nie jestem pewien jak to zrobić w czystym pythonie (NumPy ma technikę memmapowania wyjaśnioną here). Nigdy nie znalazłem jasnych i prostych odpowiedzi na to pytanie, ale mam nadzieję, że może to wskazywać na nowe kierunki. Daj nam znać, co robisz!

1

Jedną z możliwości jest utworzenie rozszerzenia C lub C++, które zapewnia interfejs Python do udostępnianych danych. Mógłbyś zapamiętywać mapę 200MB surowych danych, a następnie mieć rozszerzenie C- lub C++ - przekazać je do usługi WSGI. Oznacza to, że możesz mieć regularne (nie udostępnione) obiekty Pythona zaimplementowane w C, które pobierają dane z jakiegoś formatu binarnego z pamięci współdzielonej. Wiem, że nie jest to dokładnie to, czego chciałeś, ale w ten sposób dane pojawiłyby się co najmniej python w aplikacji WSGI.

Jeśli jednak dane zawierają wiele bardzo małych obiektów, ważne jest, aby nawet "punkty wejścia" znajdowały się w pamięci współdzielonej (w przeciwnym razie będą tracić zbyt dużo pamięci). Oznacza to, że musisz upewnić się, że wskaźniki PyObject *, które tworzą interfejs dla twoich danych, same wskazują na pamięć współdzieloną. Oznacza to, że same obiekty Pythona musiałyby znajdować się we wspólnej pamięci. O ile mogę przeczytać oficjalne dokumenty, nie jest to tak naprawdę obsługiwane. Jednak zawsze możesz wypróbować "ręczne" obiekty Pythona we wspólnej pamięci i sprawdzić, czy działa. Zgaduję, że to zadziała, dopóki interpreter Pythona nie spróbuje uwolnić pamięci. Ale w twoim przypadku nie będzie, ponieważ jest długowieczny i tylko do odczytu.

1

Trudno udostępniać rzeczywiste obiekty python, ponieważ są one powiązane z przestrzenią adresową procesu. Jeśli jednak używasz mmap, możesz tworzyć bardzo użyteczne obiekty udostępnione. Stworzyłem jeden proces do wstępnego załadowania danych, a reszta mogłaby z niego skorzystać. Znalazłem całkiem dobry wpis na blogu, który opisuje, jak można to zrobić: http://blog.schmichael.com/2011/05/15/sharing-python-data-between-processes-using-mmap/

Powiązane problemy