Inter process semaphores in shared memory

Door stereohead op zondag 22 september 2013 16:11 - Reacties (7)
Categorie: -, Views: 2.346

Intro


Voor een projectje wat misschien ooit gaat plaatsvinden heb ik behoefte aan snelle (low latency) en snelle (high bandwidth) communicatie tussen processen. Hier heeft men een naam voor bedacht, namelijk: Inter Process Communication oftewel IPC.

Goed. Ik wil dus grote (eerder MB's dan KB's) blokken data transporteren tussen twee processen. Probleem: relatief grote blokken data kopieren kost relatief veel tijd. Maar wat als we de date niet hoeven te kopieren...?

Enter shared memory.

Shared memory is een IPC techniek waarbij twee (of meer) processen het zelfde geheugenblok in hun address ruimte hebben staan. Wanneer het ene proces dan naar dat geheugenblok schrijft zal dat vervolgens door een ander proces uit dat gehugenblok gelezen kunnen worden.

Probleem: hoe weet ik dat het ene proces klaar is met schrijven, zodat het andere proces veilig uit het gedeelde gehugen kan lezen? Of: Hoe weet ik dat het andere proces iets nieuws in het gedeelde geheugen heeft gezet?

Enter semaphores.

Met semaphores kan men er voor zorgen dat maar een proces tegelijk een bepaalde resource gebruikt. De resource is in ons geval dus het gedeelde geheugenblok. Wanneer het ene proces iets wil lezen uit het gedeelde geheugen zal het sem_wait aanroepen, welke net zolang blockt totdat een ander proces sem_post heeft aangeroepen.

Nu heeft men op linux beschikking over twee soorten semaphoren, namelijk de named semaphores, en de unnamed semaphores*.

Het verschil:

Named semaphores geeft men een naam, waarna deze door elk ander proces** op het system te zien en te gebruiken is. Het aantal named semaphores is gelimiteerd omdat het voor elke semaphore een bestand opend, en het aantal open bestanden per proces door de kernel gelimiteerd word (standaard 1024, is wel aan te passen, maar toch).

Unnamed semaphores hebben geen naam, en zijn alleen te gebruiken binnen threads of processen die een gedeeld stuk geheugen hebben. (Hey toevallig, dat hebben we).

Het liefst gebruik ik unnamed semaphores, omdat ik me dan geen zorgen hoef te maken over het verwijderen van de semphores bij het afsluiten (of crashen) van het programma, en omdat ik op die manier vrijwel geen limiet op het aantal semaphores heb.


Named vs unnamed semaphores


Maargoed, in het begin zei ik dat low latency een eis was, tijd dus om te kijken hoelang het wachten op een semaphore eigenlijk duurt. Hierbij wil ik kijken wat het verschil is tussen named en unnamed semaphores, en kijken welke vorm van shared memory het snelste is.

De eerste kandidaad: de named semahore!

Hiervoor heb ik twee programmatjes geschreven, de ene maakt de semaphore, gaat wachten tot de semaphore 'gepost' is, en print vervolgens de huidige tijd. Het tweede programmatje opent de gemaakte semaphore, print de huidige tijd en doet een 'post' op de semaphore. Het eerst programma wordt opgestart deze gaat vervolgens wachten op de semaphore. Nu wordt het tweede programma opgestart, deze print de tijd en 'post' de semaphore, waardoor het eerste programma niet meer hoeft te wachten, vervolgens de tijd print en afsluit. De waarden die hier uitkomen heb ik genoteerd en zo komen we tot de volgende uitkomst:

0.0700 ms.

De tweede kandidaad: de unnamed semaphore!

Weer twee programmatjes, nu wordt er een stuk geheugen gedeeld via mmap, waarbij de mapping wordt gedaan op een regulier bestand***. De semaphores worden geinitializeerd in deze mapping, en vervolgens de programmatjes gedraait. Het resultaat:

35.1566 ms.

Oef een flinke tegenvaller, semaphores via shared memory zijn dus een stuk trager.
Maar wacht, ik deed een mmap op een regulier bestand, wat als ik een mmap doe op een gedeeld geheugen verkregen door shm_open.

Kandidaad drie, de unnamed semaphore in een mmap op shared memory verkregen via shm_open!

Het resultaat:

0.0681 ms.

Yes, dat lijkt er meer op, maar waarom is dit zoveel sneller? Even verdiepen in de manpages leert mij dat shared memory via shm_open terecht komt in de map /dev/shm, 'toevallig' is deze map gemount op een tmpfs bestandssysteem, zou het daarom sneller zijn dan mijn vorige poging?

Kandidaad vier, die unnamed semaphore in een shared memory op een regulier bestand op een tmpfs bestandsysteem.

Ik heb mijn /tmp/ folder gemount tmpfs. Voor de vierde kandidaad heb ik dus een bestand aangemaakt in mijn /tmp/ folder, de programmatjes aangepast zodat de mmap gebeurt op dit bestand en hoppa.

Het resultaat:

0.0713 ms.


Conclusie


Wat hebben we geleerd:

Named semaphores zijn niet trager dan unnamed semaphores via shared memory, afhankelijk van waar dit shared memory op gebasseerd is. Ik kwam er later trouwens achter dat named semaphores ook een entry krijgen in /dev/shm en dus waarschijnlijk ook op de achtergrond een shared memory hebben op een bestand op een tmpfs.

Eigenlijk verbaasd mij dit wel, ik had verwacht dat de kernel de pages van het shared memory gewoon in het werkgeheugen heeft staan en het onderliggende bestandssysteem dus eigenlijk helemaal geen invloed zou moeten hebben.

Nog een leuk detail, tijdens het schrijven van deze post kwam ik er achter dat ik bij de berekende tijd ook de tijd opnam van het 'printf' gedeelte. Gelukkig maakte dit niet erg veel verschil.




* Niet helemaal waar, er zijn ook nog de oude System V semaphores, maar dat is geen POSIX standaard, en het wordt niet meer aanbevolen om ze te gebruiken.

** Wanneer het daar de rechten toe heeft.

*** Een normaal, leesbaar bestand op een ext4 bestandssysteem.

Source:
https://gist.github.com/stereohead/6662398
https://gist.github.com/stereohead/6662424

RE: Klereherrie

Door stereohead op dinsdag 02 maart 2010 22:00 - Reacties (9)
Categorie: Muziek, Views: 2.696

Mucias: a music collecting/tagging daemon

Door stereohead op woensdag 14 oktober 2009 19:22 - Reacties (15)
Categorieën: Muziek, Python, Views: 2.881

Intro


Als sinds jaar en dag ben ik op zoek naar software waarmee ik mijn muziek collectie kan beheren. Onder beheren versta ik twee dingen:
  • De juiste tags koppelen aan de bestanden.
  • Een makkelijke manier om door de collectie te browsen.
Nu zijn er al veel programma's geschreven die deze twee dingen (gedeeltelijk) implementeren, maar geen voldoen aan mijn eisen. Het moet namelijk ook goed werken met grote collecties, het moet automatisch nieuwe bestanden toevoegen, het moet als een daemon draaien op mijn server (zonder GUI), het moet werken op linux, en als het kan open-source zijn.

Aangezien er praktisch geen programma's zijn die aan al deze eisen voldoen, was er nog maar één mogelijkheid: Zelf maken, maar dan wel goed...

Lees verder »

Het nummer waar ik kippenvel bij krijg

Door stereohead op dinsdag 01 september 2009 22:44 - Reacties (35)
Categorie: Muziek, Views: 4.173

Soms heb je van die nummers waarbij je kippenvel krijgt, bij de meeste van die nummers gaat dat over na het een aantal geluisterd te hebben. Toch is er één nummer die ik als maar door kan luisteren:



Bij welk nummer krijgen jullie kippenvel?

webprint.nl foto-uploader in Python

Door stereohead op zondag 16 augustus 2009 22:36 - Reacties (11)
Categorie: Python, Views: 4.164

Ik druk regelmatig wat foto's af via de online foto-afdruk dienst van webprint.nl. Meestal gaat dit om kleine hoeveelheden van max. 20 stuks. Je foto's moet je daar uploaden via een flashformulier, allemaal leuk en aardig, maar het moet allemaal een voor een.

Binnenkort wil ik een grote hoeveelheid foto's afdrukken, zeker > 100, en ik heb niet bepaald zin om een hele dag bezig te zijn met het uploaden van een stapel foto's.

Dat moet dus makkelijker, tijd om Wireshark erbij te pakken, en eens te bekijken hoe de foto's worden verstuurd.

Na wat zoeken bleek dat er drie dingen moeten gebeuren om een foto te uploaden.

1) Inloggen
2) Upload-id verkrijgen
3) Foto-uploaden

Deze drie dingen moesten dus worden omgezet in een python script. Gelukkig gaat dat super makkelijk met de hulp van httplib en minidom, en een paar uur en 328 regels code verder had ik een simpel programma dat m'n foto's upload.

Handig voor mij, maar ik wil het graag delen met de rest van de wereld dus bij deze:
broncode download (opslaan als webprint-uploader.py)

Je gebruikt het als volgt:

python webprint-uploader -u username -p password -d foto-directory -f map-waarin-je-fotos-komen


username en password spreken voorzich, dat zijn de inloggegevens voor webprint.nl
met -d geef je de map aan waarin je foto's staan, en met -f geef je aan in welke map op webprint.nl de foto's komen. Deze map wordt zonodig aangemaakt.

Ik heb het alleen getest op linux (ubuntu 9.04) maar dikke kans dat het ook op windows werkt.

That's it, ik hoop dat jullie er wat aan hebben :)