Ik ben bezig met een serverapplicatie voor een bestaand spel. Mede doordat ik nu thuis een SMP systeempje heb en door de opkomst van dual core processoren, en omdat het me gewoon interesseert, zou ik graag eens multi-threading gebruiken in mijn applicatie. Ik ben er echter nog niet zeker van hoe.
Clients kunnen connecten naar de server en wisselen tussen bepaalde maps. Alles wordt nu gedaan in één grote event loop die sockets poll't, kijkt of er timers moeten runnen en een aantal andere zaken. Nu is het zo dat dit in mijn test omgeving met max misschien 3 clients nog wel prima gaat. Ik ben echter bang, omdat er nog wel eens heel veel clients tegelijk geconnect kunnen zijn, dat de performance en responsive-heid (nederlands?
) erg achteruit kan gaan, vooral omdat je soms gewoon moet wachten op database/socket acties, system calls e.d.
Nou heb ik zelf al een aantal opties bedacht waar ik threads voor zou kunnen gebruiken:
Nog een probleem waar ik erg mee zit is locking. Denk even dit scenario in:
De client lijst is een vector. Deze moet gelocked worden voor elke thread die ermee wil gaan werken, omdat het natuurlijk niet ineens mag gebeuren dat andere threads er clients uit gaan deleten of clients die nog niet "klaar" zijn toevoegen. Nou kan dit natuurlijk prima, maar denk eens in dat als 1 thread de socket I/O afhandelt die natuurlijk de lijst moet locken, en dan pollen. Dat kan nogal eens lang duren, waarna thread 2 de client lijst lockt omdat hij een client actie gaat afhandelen (de client mag natuurlijk niet ineens gedelete worden tijdens dit proces). Hierop zitten thread 1 en de rest weer te wachten tot de lock wordt vrijgegeven. Hierbij krijg ik dus het gevoel dat ik eigenlijk gewoon een single threaded applicatie aan het schrijven ben, omdat de overige threads eigenlijk altijd wel op een lock zitten te wachten, omdat eigenlijk elke actie wel met een client te maken heeft.
Lang verhaal, maar hier zit ik dus eigenlijk mee
Als jullie zo'n soortgelijke applicatie zouden moeten ontwikkelen, hoe zouden jullie dan multithreading implementeren?
Clients kunnen connecten naar de server en wisselen tussen bepaalde maps. Alles wordt nu gedaan in één grote event loop die sockets poll't, kijkt of er timers moeten runnen en een aantal andere zaken. Nu is het zo dat dit in mijn test omgeving met max misschien 3 clients nog wel prima gaat. Ik ben echter bang, omdat er nog wel eens heel veel clients tegelijk geconnect kunnen zijn, dat de performance en responsive-heid (nederlands?
Nou heb ik zelf al een aantal opties bedacht waar ik threads voor zou kunnen gebruiken:
- Één thread voor elke client. Het grote nadeel hiervan vind ik dat je met veel users online heel veel threads kan hebben lopen. Dit lijkt me dus niet zo'n goed idee. Ik wil ervanuit gaan dat er een onbeperkt aantal users geconnect kunnen zijn, ookal zal dit in de praktijk vast niet mogelijk zijn.
- Socket polling in 1 thread, en AI/Timers in een ander. Hierbij krijg ik het idee dat het vaak kan voorkomen dat 1 thread heel erg veel werk te doen heeft en de ander praktisch uit z'n neus zit te vreten. Ik zou dit graag wat meer balanceren.
- Elke map op 1 thread draaien. Zou wellicht een goeie optie zijn, alhoewel je dan ook weer krijgt dat maps met veel users erop veel meer cpu trekken dan maps die leeg zijn. Ook omdat er soms vrij veel maps tegelijk geladen kunnen zijn zouden er hier ook vrij veel threads tegelijk moeten draaien.
Nog een probleem waar ik erg mee zit is locking. Denk even dit scenario in:
De client lijst is een vector. Deze moet gelocked worden voor elke thread die ermee wil gaan werken, omdat het natuurlijk niet ineens mag gebeuren dat andere threads er clients uit gaan deleten of clients die nog niet "klaar" zijn toevoegen. Nou kan dit natuurlijk prima, maar denk eens in dat als 1 thread de socket I/O afhandelt die natuurlijk de lijst moet locken, en dan pollen. Dat kan nogal eens lang duren, waarna thread 2 de client lijst lockt omdat hij een client actie gaat afhandelen (de client mag natuurlijk niet ineens gedelete worden tijdens dit proces). Hierop zitten thread 1 en de rest weer te wachten tot de lock wordt vrijgegeven. Hierbij krijg ik dus het gevoel dat ik eigenlijk gewoon een single threaded applicatie aan het schrijven ben, omdat de overige threads eigenlijk altijd wel op een lock zitten te wachten, omdat eigenlijk elke actie wel met een client te maken heeft.
Lang verhaal, maar hier zit ik dus eigenlijk mee