2015-02-17 13 views
10

Ich habe einen Python-Prozess als WSGI-Apache-Server dienen. Ich habe viele Kopien dieses Prozesses auf jeder von mehreren Maschinen ausgeführt. Ungefähr 200 Megabyte meines Prozesses sind schreibgeschützte Python-Daten. Ich möchte diese Daten in einem Memory-Mapped-Segment platzieren, damit die Prozesse eine einzelne Kopie dieser Daten gemeinsam nutzen können. Am besten wäre es, an diese Daten anhängen zu können, so dass sie tatsächlich Python 2.7-Datenobjekte sein könnten, anstatt sie aus etwas wie Gurke oder DBM oder SQLite zu analysieren.Wie einfach zu speichern Python nutzbare schreibgeschützte Datenstrukturen im Shared Memory

Hat jemand Beispielcode oder Zeiger auf ein Projekt, das dies zum Teilen getan hat?

+0

"Ungefähr 200 Megabytes meines Prozesses sind schreibgeschützte Python-Daten." Ich konnte diesen Teil nicht verstehen. Können Sie einige Details angeben? Welche Art von Daten? Was hast du versucht? –

+1

Welches Betriebssystem verwenden Sie und wie laufen Ihre Prozesse?Wenn Sie 'vfork' verwenden, teilt das Kind eine Kopie der Seiten seiner Eltern, bis es trotzdem auf sie schreibt. –

+0

Warum sollte Redis nicht Ihr Problem lösen? –

Antwort

1

Da es sich um schreibgeschützte Daten handelt, müssen Sie keine Aktualisierungen zwischen Prozessen teilen (da keine Aktualisierungen vorhanden sind). Ich schlage vor, dass Sie in jedem Prozess eine lokale Kopie davon behalten.

Wenn Speicherbeschränkungen ist ein Problem, das Sie einen Blick auf mit multiprocessing.Value oder multiprocessing.Array ohne Sperren für diese haben: https://docs.python.org/2/library/multiprocessing.html#shared-ctypes-objects

Andere als dass Sie auf einem externen Prozess verlassen haben und einige Serialisierung dieses zu erhalten getan Ich würde Redis oder Memcached sehen, wenn ich du wäre.

3

This post von @modelnine auf StackOverflow bietet eine wirklich große umfassende Antwort auf diese Frage. Wie er bereits erwähnt hat, kann die Verwendung von Threads anstelle von Prozess-Forking in Ihrem Webserver die Auswirkungen dieser Lektion deutlich machen. Ich ran into a similar problem trying to share extremely-large NumPy arrays zwischen CLI Python-Prozesse mit einigen Arten von Shared Memory vor ein paar Jahren, und wir am Ende mit einer Kombination aus einer sharedmem Python-Erweiterung, Daten zwischen den Arbeitern zu teilen (die Speicher in bestimmten Fällen Leck, aber, es ist reparierbar wahrscheinlich). Ein schreibgeschütztes mmap()-Verfahren könnte für Sie arbeiten, aber ich bin nicht sicher, wie man das in pure-python macht (NumPy hat eine Memapping-Technik erklärt here). Ich habe nie eine klare und einfache Antwort auf diese Frage gefunden, aber hoffentlich kann dies Sie in einige neue Richtungen weisen. Lass uns wissen, was du am Ende machst!

1

Eine Möglichkeit besteht darin, eine C- oder C++ - Erweiterung zu erstellen, die eine Pythonic-Schnittstelle für Ihre gemeinsamen Daten bereitstellt. Sie könnten 200 MB Rohdaten speichern und dann die C- oder C++ - Erweiterung dem WSGI-Dienst zur Verfügung stellen. Das heißt, Sie könnten reguläre (nicht gemeinsam genutzte) Python-Objekte in C implementiert haben, die Daten aus einer Art von Binärformat im Shared Memory abrufen. Ich weiß, dass das nicht genau das ist, was Sie wollten, aber so würden die Daten zumindest für die WSGI-App pythonisch erscheinen.

Wenn jedoch Ihre Daten aus sehr vielen sehr kleinen Objekten bestehen, dann ist es wichtig, dass sich sogar die "Einstiegspunkte" im gemeinsamen Speicher befinden (sonst werden sie zu viel Speicher verschwenden). Das heißt, Sie müssen sicherstellen, dass die PyObject * -Zeiger, die die Schnittstelle zu Ihren Daten bilden, tatsächlich selbst auf den gemeinsamen Speicher zeigen. Das heißt, die Python-Objekte selbst müssten sich im Shared Memory befinden. Soweit ich die offiziellen Dokumente lesen kann, wird dies nicht wirklich unterstützt. Sie könnten jedoch immer versuchen, Python-Objekte im Shared Memory "zu bearbeiten" und sehen, ob es funktioniert. Ich schätze, es würde funktionieren, bis der Python-Interpreter versucht, den Speicher freizugeben. Aber in Ihrem Fall wird es nicht, da es langlebig und schreibgeschützt ist.

1

Es ist schwierig, tatsächliche Python-Objekte zu teilen, da sie an den Prozessadressraum gebunden sind. Wenn Sie jedoch mmap verwenden, können Sie sehr nützliche gemeinsame Objekte erstellen. Ich würde einen Prozess erstellen, um die Daten vorab zu laden, und der Rest könnte sie verwenden. Ich habe einen ziemlich guten Blogpost gefunden, in dem beschrieben wird, wie es gemacht werden kann: http://blog.schmichael.com/2011/05/15/sharing-python-data-between-processes-using-mmap/