Check alle échte Black Friday-deals Ook zo moe van nepaanbiedingen? Wij laten alleen échte deals zien

Server forken?

Pagina: 1
Acties:

  • Black-Xjuh
  • Registratie: Oktober 2002
  • Laatst online: 20-10 16:34
Ik heb een server die verbindingen onderhoud met apparaten.

In grote lijnen is het zo opgebouwd dat er een main is die luistert en verbindingen accepteert. Elke verbinding krijgt zijn eigen thread die wacht totdat het apparaat iets periodiek verzend.

Elke thread vult op het moment dat hij iets ontvangt een buffertje met de ontvangen stream.

Deze stream van bytes worden vervolgens één voor één verwerkt. De stream gaat dus een functie in die er een mutex opgooit en deze mutex gaat er weer vanaf als die klaar is en dan wordt de volgende stream er weer in gegooid door een van de threads.

Het aantal apparaten is echter gegroeid en er zal dus een grens aan komen dat die ene functie met de mutex het niet meer aan kan. Ik wil dus meerdere simultaan laten draaien.

Het punt is dus alleen dat die lock niet voor niks is en ze dus niet door elkaar mogen lopen. Het lijkt mij dus dat een thread niks wordt (gedeeld geheugen)? Zou het forken van dit proces wel een optie zijn?

  • Grijze Vos
  • Registratie: December 2002
  • Laatst online: 28-02 22:17
Wat mag er niet precies simultaan draaien? Volgens mij mist er nog iets in je verhaal om een zinnig antwoord te kunnen geven. Heb je een kleine relevante snippet code oid?

Op zoek naar een nieuwe collega, .NET webdev, voornamelijk productontwikkeling. DM voor meer info


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 28-11 08:35

curry684

left part of the evil twins

Wat jij nodig hebt heet een thread pool en goeie job distribution.

Professionele website nodig?


  • prototype
  • Registratie: Juni 2001
  • Niet online

prototype

Cheer Bear

Als ik het dus goed begrijp uit je verhaal muteren alle threads (connecties) in feite dus 1 gemeenschappelijke buffer die "beschermd" is met een mutex? Heb je wel eens overwogen om een server te maken zonder threads? Zoek eens op evented servers. Die halen in de praktijk een veel hogere throughput ook en je hebt geen last meer van stomme locks als 't goed is ;-) Keywords om op te zoeken: non-blocking IO, eventloop, callbacks.

De manier waarop jij de server bouwt is een beetje het klassieke 1 thread per connectie model, die niet lekker opschaalt. Bovendien krijg je last van het zogenaamde thundering herd probleem, waarbij je bij een activiteit op de server socket oppeens alle threads wakker maakt, terwijl er maar 1 door mag gaan. Dit is vrij inefficient als je veel threads hebt. Zou even ook zoeken op dat onderwerp in papers.

[ Voor 32% gewijzigd door prototype op 30-06-2010 18:19 ]


  • Soultaker
  • Registratie: September 2000
  • Laatst online: 23:02
Black-Xjuh schreef op woensdag 30 juni 2010 @ 16:37:
Het punt is dus alleen dat die lock niet voor niks is en ze dus niet door elkaar mogen lopen. Het lijkt mij dus dat een thread niks wordt (gedeeld geheugen)? Zou het forken van dit proces wel een optie zijn?
Wat los je daarmee op? Als er bepaalde dingen niet tegelijk mogen gebeuren, kan dat ook niet als ze in aparte processen lopen. Je hebt al een multithreaded omgeving. Als je meer overlap tussen threads wil krijgen moet je dus zorgen dat die exclusieve lock verdwijnt door meer fine-grained locking te introduceren.
Het aantal apparaten is echter gegroeid en er zal dus een grens aan komen dat die ene functie met de mutex het niet meer aan kan.
Tien threads parallel draaien genereert op zichzelf niet minder werk dan één thread die tien taken achter elkaar uitvoert. Eerder het tegenovergestelde. Er zijn slechts twee voordelen van multithreading:
  1. kortlopende taken hoeven niet te wachten op langlopende taken (omdat taken niet in een vaste volgorde uitgevoerd worden) waardoor de latency lager kan worden;
  2. je kunt een hogere doorvoersnelheid behalen door van meerdere cores te profiteren.
Of het eerste een probleem is, is uit je vraag niet duidelijk. Als alle bewerkingen ongeveer even lang duren is er weinig aanleiding om ze uit volgorde te behandelen. Het tweede zou een motivatie voor betere multithreading kunnen zijn, maar dat is vooropgesteld dat die seriële functie nu ook echt een bottleneck vormt. Uit je verhaal blijkt helemaal niet dat dat nu het geval is.

Verwijderd

Grijze Vos schreef op woensdag 30 juni 2010 @ 16:49:
Wat mag er niet precies simultaan draaien? Volgens mij mist er nog iets in je verhaal om een zinnig antwoord te kunnen geven. Heb je een kleine relevante snippet code oid?
Volgens mij mis ik ook iets.

Probeer een oplossing te krijgen waardoor de lock niet meer/minder nodig is zou ik eerst zeggen :+

Maar goed, eerst wat meer informatie zou makkelijk zijn :)

Hoe wordt de stream bijvoorbeeld opgevangen, en waar wordt deze naartoe geschreven?

  • voodooless
  • Registratie: Januari 2002
  • Laatst online: 11:20

voodooless

Sound is no voodoo!

prototype schreef op woensdag 30 juni 2010 @ 18:17:
Als ik het dus goed begrijp uit je verhaal muteren alle threads (connecties) in feite dus 1 gemeenschappelijke buffer die "beschermd" is met een mutex? Heb je wel eens overwogen om een server te maken zonder threads? Zoek eens op evented servers. Die halen in de praktijk een veel hogere throughput ook en je hebt geen last meer van stomme locks als 't goed is ;-) Keywords om op te zoeken: non-blocking IO, eventloop, callbacks.
Tja, de waarheid ligt waarschijnlijk ergens in het midden. Asynchrone IO systemen zijn ook zelden single threaded. Ze weken meestal met een thread pool, die een aantal worker threads gebruikt om alle IO af te handelen. Het voordeel hiervan is dat je veel minder context switches hebt t.o.v een thread per connectie model. Je moet hierbij echter opletten dat je event handlers niet teveel doen. Eigenlijk zijn het niet meer dan verdelde interrupt routines. Duurt het te lang, loopt je hele io trager.

Ik ben wel heel benieuwd wat je in die lock doet, en hoe je weet dat dit de bottleneck is.

[ Voor 4% gewijzigd door voodooless op 30-06-2010 19:54 ]

Do diamonds shine on the dark side of the moon :?


  • Herko_ter_Horst
  • Registratie: November 2002
  • Niet online
De vraag is wat de contested resource is die ervoor zorgt dat dingen niet parallel kan doen. Is daar niet wat op te lossen?

"Any sufficiently advanced technology is indistinguishable from magic."


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 28-11 08:35

curry684

left part of the evil twins

prototype schreef op woensdag 30 juni 2010 @ 18:17:
Als ik het dus goed begrijp uit je verhaal muteren alle threads (connecties) in feite dus 1 gemeenschappelijke buffer die "beschermd" is met een mutex? Heb je wel eens overwogen om een server te maken zonder threads? Zoek eens op evented servers. Die halen in de praktijk een veel hogere throughput ook en je hebt geen last meer van stomme locks als 't goed is ;-) Keywords om op te zoeken: non-blocking IO, eventloop, callbacks.
Schaalt ook zo lekker op je dual-quadcore hyperthreaded server.

Nu ik nog eens de openingspost lees trouwens heb ik overigens het gevoel dat de funneling dermate is dat de synchronizatie de hele multithreading weer ongedaan maakt. Al met al denk ik dat TS een ontwerpprobleem heeft, geen programmeerprobleem.

Professionele website nodig?


  • prototype
  • Registratie: Juni 2001
  • Niet online

prototype

Cheer Bear

curry684 schreef op woensdag 30 juni 2010 @ 21:37:
[...]

Schaalt ook zo lekker op je dual-quadcore hyperthreaded server.
De meeste servers die ik ben tegen gekomen zijn IO bound, niet CPU bound. Daarbij kun je ook door meerdere evented server processen te starten schalen: zie b.v. nodejs.org, maar dat hangt natuurlijk af van je applicatie ook. Alleen omdat een server singlethreaded is moet je niet denken dat ze niet kunnen schalen, je vergeet dan processen ;-) Wel wat zwaarder uiteraard in dat geval tov threads.

Zou je dat doortrekken en ipv processen threads gebruiken dan kan je het maximale uit je systeem halen; je zou dan per core een thread een event loop kunnen laten draaien. Beter dan dat krijg je volgens mij niet.

Voor de probleemstelling van TS lijkt me threads onnodig iig en een evented server zou volgens mij veel betere resultaten moeten yielden hierin aangezien ik uit zijn verhaal het vermoeden krijg dat de bottleneck bij de mutex opeisen ligt, i.e. ik kan niet zien uit zijn verhaal waarom threading nodig zou zijn.

Mooiste oplossing is natuurlijk als je de afweging maakt om zowel threading als asynchronous IO te gebruiken; je zou dan een threadpool idd kunnen gebruiken voor je workers, en in een eventloop de dispatching ervoor kunnen voorzien. Die dispatch thread doet dan ook alleen maar dat. Zo zou je als 't goed is heel veel connecties aan moeten kunnen en de volledige CPU kunnen gebruiken. Je schrijft dan bij wijze van spreken je eigen scheduler voor m "green threads" die gemapped zijn op n kernel threads. Dit is een methode die erlang b.v. ook gebruikt om duizendveel connecties aan te kunnen. Maar thread interactie incurred een aardige overhead en ik zou deze methode eigenlijk alleen aanraden als je handler zoiets als 1+ sec verwacht te doen met de processing. Anders is een single threaded reactor beter.

[ Voor 16% gewijzigd door prototype op 01-07-2010 00:22 . Reden: Even wat toelichting ]


  • curry684
  • Registratie: Juni 2000
  • Laatst online: 28-11 08:35

curry684

left part of the evil twins

prototype schreef op woensdag 30 juni 2010 @ 22:34:
[...]

Alleen omdat een server singlethreaded is moet je niet denken dat ze niet kunnen schalen, je vergeet dan processen ;-) Wel wat zwaarder uiteraard in dat geval tov threads.
Ik heb wel wat ervaring met de architectuur van fabrieksautomatisering hoor ;) TS omschrijft "dat er een main is die luistert en verbindingen accepteert", dat is alleen multithreaded goed performend te doen omdat anders de overhead van congestion te zwaar is, juist omdat IO zoveel waitstates elders uitlokt. De uitzondering op de regel hiervan, Apache's prefork MPM, compenseert dit doordat de afhandeling van iedere verbinding dermate zwaar is dat de IPC-overhead niet meer relevant is.

Hoe dan ook heb je natuurlijk gelijk in dat we niet genoeg informatie hebben om de situatie echt goed van advies te kunnen voorzien. Wellicht is evented wel beter, wellicht is preforken een optie :)

[ Voor 11% gewijzigd door curry684 op 01-07-2010 01:43 ]

Professionele website nodig?


  • prototype
  • Registratie: Juni 2001
  • Niet online

prototype

Cheer Bear

curry684 schreef op donderdag 01 juli 2010 @ 01:38:
[...]

Ik heb wel wat ervaring met de architectuur van fabrieksautomatisering hoor ;) TS omschrijft "dat er een main is die luistert en verbindingen accepteert", dat is alleen multithreaded goed performend te doen omdat anders de overhead van congestion te zwaar is, juist omdat IO zoveel waitstates elders uitlokt. De uitzondering op de regel hiervan, Apache's prefork MPM, compenseert dit doordat de afhandeling van iedere verbinding dermate zwaar is dat de IPC-overhead niet meer relevant is.
Wat versta je precies met congestion? Mensen hebben hier vaak een wat bredere interpretatie op dus ik vraag 't maar even. "Een main die luistert en verbindingen accepteert" is qua goede performance niet voorbehouden aan multithreading denk ik; operating systems bieden vaak op kernel niveau goede support voor asynchronous IO, en denk daarbij in het bijzonder op linux aan epoll waarbij je een set aan filedescriptors kan monitoren op read-readiness. Dat moet makkelijk een shitload aan fd's / connecties aan kunnen op 1 thread in ieder geval, sterker nog, nginx gebruikt voor zover ik weet ook een soortgelijke opzet en performed gigantisch beter ;-) Die kan op z'n dooie gemak zeg maar met 50k simultane connecties aan door dit, dat heb ik Apache prefork MPM nog niet zien doen iig ;-) Again, hangt af van je app, maar de meeste server toepassingen die ik heb gezien zijn IO bound en niet CPU bound.

Je kan je systeem helemaal benutten in ieder geval door per core een thread te starten en daar op elk een event loop op te draaien, wederom uitgaande van IO bound toepassing. Net als jij heb ik daar ook wel een beetje ervaring in zowel apache als nginx in omgevingen als linkedin etc... (http://modrails.com) ;-)

[ Voor 8% gewijzigd door prototype op 01-07-2010 02:36 ]


  • Black-Xjuh
  • Registratie: Oktober 2002
  • Laatst online: 20-10 16:34
Ik heb de reacties even doorgenomen en ben daar uit wel wat wijzer geworden.

Zelf ben ik ook nog bezig geweest met de server en heb wat dingetjes ontdekt..

Door middel van wat timing dingetjes heb ik dus ontdekt dat die lang wacht tot de mutex vrij is. De thread gaat dus naar de mutex en geeft dan zijn id weer met de huidige tijd, vervolgens geef die ook weer zijn id weer met de huidige tijd als die de mutex voorbij is. Dit is telkens zo'n 10 / 15 seconde verschil. Waar deze grote vertraging vandaan komt weet ik niet.

Waar ik ook tegen op liep is dat die bij het afhandelen in die mutex dus wat queries uitvoert op een externe database. Het begin tot het eind van de mutex duurt 0,7 seconde met deze queries en 0,03 seconde zonder deze queries. Oftewel, dat MySQL gedeelte is de daadwerkelijke bottleneck.

De reden waarom ik dacht aan fork was ook dit gedeelte, de mutex handelt door de mutex elk apparaat netjes een voor een af. De reden van de mutex is dat verschillende apparaten niet in elkaar zijn variabelen mogen rommelen en ik dacht dat ik met fork deze variabelen opnieuw aan maak? Wat hiervan in mijn ogen het voordeel zou zijn is dat ik dan meerdere van deze lusjes naast elkaar kan draaien en ook meerdere connecties kan maken met de database. Elk apparaat wordt dus onmiddellijk geaccepteerd en afgehandeld ipv dat die moet wachten op het vorige apparaat.

Dit werkt overigens alleen er van uitgaande dat ik met meerde db connecties waar ik de queries mee uitvoer het verwerken sneller gaat.

Wat ik me nu had bedacht was om ipv in de mutex de queries een voor een uit te voeren elke query in een thread te gooien? Of de queries in een buffer achter elkaar en dan een instelbaar aantal threads die deze queries afwerken?

Wat de vraag dan wel is, als ik een buffer heb met 1000 queries, gaat het dan sneller als je deze queries laat afhandelen door 10 threads die er allemaal 100 simultaan doen of kan je net zo goed 1 thread die 1000 laten doen omdat die elke query 10x zo snel doet?

edit:
Wat jullie al zeiden, de mutex is in principe niet de bottleneck, uiteindelijk wel maar die wordt veroorzaakt door de MySQL queries.

[ Voor 3% gewijzigd door Black-Xjuh op 01-07-2010 10:37 ]

Pagina: 1