Meerdere threads zo efficient mogelijk

Pagina: 1
Acties:

  • Xorgye
  • Registratie: Maart 2005
  • Laatst online: 05-10-2024
Tja, ik heb sinds kort uitgevonden dat threads een zeer welkome optie zijn in het programmeren.

Nu zit ik mij af te vragen wat de juiste implementiatie zal zijn als je niet wilt dat de threads elkaar gaan 'bijten' dus dat ze informatie tegelijkertijd aanroepen en veranderen zonder dat de ander weet dat diegene er ook mee bezig is.

Je hebt natuurlijk het eerste programma wat gestart word... heel mooi, HoofdThread
Deze zal een sub thread ThreadC starten
Ook start HoofdThread sub thread ThreadG

Het blijft natuurlijk allemaal erg vaag als we gaan spreken over 'iets' dus neem ik ff als voorbeeld een simpele grafische engine:
HoofdThread handelt de invoer van de toetsenbord maar ook netwerk af, want de hoofdthread draait toch.
ThreadC draait de Collission van de objecten en onthoud waar objecten zijn
ThreadG draait het Grafische aspect en zorgt ervoor dat alle informatie uit ThreadC weergegeven word.

Nou, nu komen er dus al wat problemen om de hoek kijken. HoofdThread, ThreadC en ThreadG draaien tegelijkertijd. Als er informatie uitgewisselt gaat worden moet dat gebeuren op een manier dat als 2 threads besluiten exact op hetzelfde moment informatie op te zoeken van een andere thread ze niet elkaar bijten.
Nu had ik als oplossing bedacht dat elke thread passief is. Het enige wat men doet is een vraag (binnen eigen beheer van de thread) neer zetten, die andere threads dan uit kunnen lezen.
Dus als ThreadC besluit dat een object gerendert gaat worden, stopt hij in zijn eigen 'uitleeslijst' de informatie en zegt op het allerlaatst dat er nieuwe informatie is. ThreadG leest deze informatie uit.
Als reactie daarop zet ThreadG in een bepaalde gereserveerde ruimte binnen het gedeelte wat hij mocht uitlezen in de 'uitleeslijst' dat hij de informatie verwerkt heeft. ThreadC weet nu dat de informatie verwerkt is, en verwijdert deze item uit zijn verwerklijst.

Zo kunnen alle functies met elkaar communiceren... lijkt mij...
Of beredeneer ik hier iets verkeerd?

Allereerst is dit een oplossing die mij makkelijk lijkt om te zetten naar een werkelijk programma, terwijl ik zelf eigenlijk alles in de hand kan houden. Geen extra libary's er bij en niet veel gezeur er omheen. Gewoon een paar regels waar je als programmeur aan moet houden en daarna geen omkijken meer naar hebt.

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

Ik zou zeggen: pak er een goed boek over concurrency control bij. Als je in Java bezig bent, dan 'Concurrent Programming in Java' van Doug Lea. En voor andere talen zijn er ook genoeg boeken te vinden (alhoewel de kennis vaak helemaal niet taal afhankelijk is).

paar toverwoorden:
lock
mutex
semafoor
monitor
kritieke sectie.

Verder wordt concurrency control beschouwd als een erg lastig onderdeel. Hier ben ik het helemaal mee eens: je krijgt een nieuwe dimensie van problemen om rekening mee te houden (aangezien ieder commando parallel naast ieder commando van een andere thread uitgevoerd kan worden). Programma`s zijn lastig te testen, bugs lastig te reproduceren en het correct functioneren van een programma gecompliceerd om te voorspellen. Dus concurrency control is in principe niet iets dat je zo maar even oplost, alhoewel je met een aantal basis technieken wel een eind kan komen (maar pas wel weer op voor allerlei liveness problems: deadlocks, livelocks, starvation).

[ Voor 55% gewijzigd door Alarmnummer op 10-04-2006 14:51 ]


  • Tomatoman
  • Registratie: November 2000
  • Laatst online: 14:21

Tomatoman

Fulltime prutser

Zoals Alarmnummer al zegt: dit is typisch iets waarvoor je boeken moet lezen. Threads zijn geen gemakkelijk onderwerp; interactie tussen threads is niet iets wat je in een paar regeltjes kunt uitleggen. Je kunt veel informatie in [rml][ Delphi] Threads en locken[/rml] vinden. Er staat dan wel [Delphi] in de topictitel, maar de meeste informatie in dat topic is platformonafhankelijk.

Een goede grap mag vrienden kosten.


  • Xorgye
  • Registratie: Maart 2005
  • Laatst online: 05-10-2024
Thanks ;)

Boeken... hmmm... k zal kijken wat r in de bieb te vinden is :+

En ik hoor overal termen van functies die men gebruikt en allemaal vage, slome windows systeemfuncties... ik wil t cross-platform hebben dus ga ik niet uit van functies die alles voor mij regelen maar dat de manieren waarop ik met alle gegevens om ga in orde is.

Maar ik weet ook dat er al gauw ontzettend veel problemen om de hoek komen kijken. Ik vroeg me af of de manier die ik zei gewoon iig voor zover het alleen om die manier ging 'goed' was... maar ik zal r dan maar experimenteel mee bezig gaan en kijken wat het resultaat is wat ik graag wil :)

Btw, wat mag er allemaal gevraagt/gezet worden in dit topic? Alleen de werking van je systeem 'op papier'?

[ Voor 24% gewijzigd door Xorgye op 10-04-2006 14:26 ]


  • MicroWhale
  • Registratie: Februari 2000
  • Laatst online: 08:16

MicroWhale

The problem is choice

over het algemeen wordt bij alle functies in een thread, die informatie van die thread veranderen, het volgende gedaan:

- grendel thread af,
- verander informatie,
- geeft thread vrij.

Dit wordt gedaan door een "kritieke sectie" ofwel CriticalSection te maken. Een kritieke sectie "ga je binnen" en "verlaat je", meer doe je er niet mee. Wat het forceert is dat een andere thread moet wachten als deze ook weer de CriticalSection "binnen wil gaan". Er mogen zich normaal gesproken niet meer dan 1 threads in hetzelfde stuk code bevinden.

Delphi:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{in je thread-object:}
TmyThread = class(TThread)
private
  FMyCriticalSection : TCriticalSection;
{.. de rest..}
end;

{in de create van TmyThread:}
  FMyCriticalSection:=TCriticalSection.Create;

{in een functie:}
  FMyCriticalSection.Enter
  try
    {voer kritieke code uit}
  finally
    FMyCriticalSection.Leave;
  end;

Het enige belangrijke is dat je vandaag altijd rijker bent dan gisteren. Als dat niet in centen is, dan wel in ervaring.


  • Xorgye
  • Registratie: Maart 2005
  • Laatst online: 05-10-2024
Aha... en dat afgrendelen kan natuurlijk alleen verricht worden door de thread die de beide threads concroleert, zodat ook niet het afgrendelen een probleem op zich word...

Maar wat voorkom je dan? Welke term hoort er bij dat een waarde door 2 functies tegelijk word verandert?

  • Xorgye
  • Registratie: Maart 2005
  • Laatst online: 05-10-2024
Dit kwam ik tegen in die Delphy thread:
Windows Synchronization Techniques

The Win32 API functions offer many further synchronization techniques:
# Critical Sections are portions of source code that cannot be executed by two threads at the same time. By using a critical section, you can serialize the executeion of specific portions of the source code. Critical sections can be used only within a single process, a single application.
# Mutexes are global objects you can use to serialize access to a resource. You first set a mutex, then access the resource, and finally release the mutex, as we saw in the OneCopy example. While the mutex is set, if another thread (or process) tries to set the same mutex, it is stopped until the mutex is released by the previous thread (or process). A mutex can be shared by different applications.
# Semaphores are similar to mutexes, but they are counted: yu could allow, for example, three and no more than three accesses to a given resource at the same time. A mutex is equivalent to a semaphore with a maximum count of 1. We'll see an example of the use of the semaphore in the section "threaded database acces" (dus niet - hezik) later in this chapter.
# Events can be used as a mean of synchronizing a thread with system events, such as user file operations. The WaitFor method of the Delphi TThread class uses an event. Events can also be used to awaken several threads at the same time.
Maar dit is allemaal erg leuk... maar kan iemand mij vertellen wat dit eigenlijk van het systeem vraagt? Als je de hele tijd bezig bent met het locken en unlocken van data gaat daar ontzettend veel processorwerk in zitten, hoe je het ook wendt of keert... en ik vind dat eigenlijk iets wat een windows-mentaliteit is: gebruik maar resources, het kan toch niet op...

Maar ik zal er maar een boek over gaan lezen denk ik zo, ik zoek echt naar de techniek ACHTER al die locks en die andere dingen...

[ Voor 1% gewijzigd door Xorgye op 10-04-2006 14:50 . Reden: *domme opmerking* ]


  • whoami
  • Registratie: December 2000
  • Laatst online: 15:46
Ik denk dat je toch best eerst eens een boek of een heel goede tutorial over threading gaat gaan opsnorren.
De steekwoorden die Alarmnummer al gaf, zijn best de moeite waard.

(Over dat 'vergrendelen': het is de data die je vergrendelt, en niet de thread imo; en het is de thread zelf die zegt 'ik ben nu met dit bezig, en jullie moeten er af blijven'.)
Maar dit is allemaal erg leuk... maar kan iemand mij vertellen wat dit eigenlijk van het systeem vraagt? Als je de hele tijd bezig bent met het locken en unlocken van data gaat daar ontzettend veel processorwerk in zitten
Da's inderdaad duur en kan je systeem vertragen (vooral omdat je op een gegeven moment de hele tijd kan blijven wachten), daarom moet je goed nagaan wat er wanneer moet gelocked worden, en wat niet.
en ik vind dat eigenlijk iets wat een windows-mentaliteit is: gebruik maar resources, het kan toch niet op...
Dit is nu eens je reinste larie; wat heeft Windows daar nu mee te maken ? Het is de taak van de programmeur om zo efficient mogelijk te zijn.

[ Voor 53% gewijzigd door whoami op 10-04-2006 14:40 ]

https://fgheysels.github.io/


  • Xorgye
  • Registratie: Maart 2005
  • Laatst online: 05-10-2024
*mijn excuses voor die opmerking over windows*
Iedereen kan het inderdaad doen...

K denk dat ik maar een simpel systeempje ga gebruiken: main thread die een lijst heeft van welke thread waarin bezig is waarmee en dat threads aan kunnen vragen aan de main thread of ze toegang tot bepaalde gegevens in een andere thread kunnen krijgen... dat is volgens mij de toepassing van een kritieke selectie samen met een lock aanvragen.

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

Xorgye schreef op maandag 10 april 2006 @ 14:38:
Maar dit is allemaal erg leuk... maar kan iemand mij vertellen wat dit eigenlijk van het systeem vraagt?

Als je de hele tijd bezig bent met het locken en unlocken van data gaat daar ontzettend veel processorwerk in zitten, hoe je het ook wendt of keert... en ik vind dat eigenlijk iets wat een windows-mentaliteit is: gebruik maar resources, het kan toch niet op...
Tja. Als je resources wilt gebruiken, dan zul je technieken moeten toepassen om het veilig te doen. Ik gebruik in de meeste gevallen isolation icm immutability icm een transactie en in slechts een paar gevallen gebruik ik 'echte' concurrency control (dus werken met locks oa). Je moet wel goed weten wanneer het handiger is om een systeem echt multithreaded te maken want soms kan het ook tegen je werken.
Maar ik zal er maar een boek over gaan lezen denk ik zo, ik zoek echt naar de techniek ACHTER al die locks en die andere dingen...
Mutexes, kritieke secties, en semaforen zijn eigelijk de basis van concurrency control bouwstenen. Veel hogere concurrency control stenen bouw je op basis van lagere bouwstenen:

Importance of higher level concurrency constructs

Dus probeer eerst die bouwstenen onder de knie te krijgen aangezien dat echt de basis stenen zijn. Later kan je dan hogere bouwstenen bekijken: readwrite locks, exchangers, blocking queues, barriers etc etc etc.

[edit]
Je kunt misschien wel besparen op concurrency bouwstenen, maar hierdoor kan je systeem soms ook minder concurrent requests aan. Kijk maar eens naar de readwritelock tov de exclusieve lock (mutex, binaire semafoor). Voor een readwritelock ben je wel een aantal exclusieve locks nodig, maar je kunt dus wel meer concurrent requests aan dan een exclusieve lock. Dus waar zit je winst? Een paar procent winst doordat je os minder overhead heeft van de locks? Of veel winst (misschien wel 100`en procenten) doordat je server een stuk sneller kan draaien (meer concurrent requests) doordat je locks op een slimmere manier toepast?

[ Voor 30% gewijzigd door Alarmnummer op 10-04-2006 16:15 ]


  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 10-12-2025
Xorgye schreef op maandag 10 april 2006 @ 14:32:
Aha... en dat afgrendelen kan natuurlijk alleen verricht worden door de thread die de beide threads concroleert, zodat ook niet het afgrendelen een probleem op zich word...
Eh nee, dat kan zeker niet. Want hoe weet die hoofdthread dat een "gecontroleerde" thread gestopt moet worden? Een correcte oplossing met Critical Sections is in de boeken te vinden.

"Zo efficient mogelijk" is overigens lang niet altijd met Critical Sections, maar dan komen we op universitair informatica nivo (Compare-And-Swap, Lock-free datastructures e.d.)

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


  • MicroWhale
  • Registratie: Februari 2000
  • Laatst online: 08:16

MicroWhale

The problem is choice

volgens mij zijn die critical sections enzo allemaal op os-nivo geregeld. je moet dus alleen ff weten welke calls je hiervoor nodig hebt. het volgendelinkje geeft aan wat de overeenkomsten voor critical sections bij win en linux zijn.

Het enige belangrijke is dat je vandaag altijd rijker bent dan gisteren. Als dat niet in centen is, dan wel in ervaring.


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

Logos schreef op dinsdag 11 april 2006 @ 08:33:
volgens mij zijn die critical sections enzo allemaal op os-nivo geregeld.
Een kritieke sectie is het gevolg van calls op synchronisatie bouwstenen zoals een mutex/semafoor etc. Kritieke secties worden niet op os nivo geregeld, maar de synchronisatie bouwstenen worden vaak wel door het os geregeld (linux,windows).

  • MicroWhale
  • Registratie: Februari 2000
  • Laatst online: 08:16

MicroWhale

The problem is choice

Alarmnummer schreef op dinsdag 11 april 2006 @ 11:10:
[...]

Een kritieke sectie is het gevolg van calls op synchronisatie bouwstenen zoals een mutex/semafoor etc. Kritieke secties worden niet op os nivo geregeld, maar de synchronisatie bouwstenen worden vaak wel door het os geregeld (linux,windows).
precies wat je zegt... :)
goed verwoord

Het enige belangrijke is dat je vandaag altijd rijker bent dan gisteren. Als dat niet in centen is, dan wel in ervaring.


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

Misschien ook leuk om te weten:
waar ik zelf bang voor was zijn grote hoeveelheden threads die liggen te slapen omdat ze een of andere kritieke sectie inwillen. Ik dacht dat de performance overhead voor het onnodig context swichten de andere processen behoorlijk kan beinvloeden. Maar moderne operating systems die kunnen uiteraard zien of een proces al weer kan draaien en zullen een proces ook niet gaan schedulen als het niet kan draaien (omdat het nog geblokkeerd is). Uiteraard heb je wel allerlei administratieve rompslomp, maar de kosten zijn een stuk minder hoog dan ik had gedacht.

Hierdoor kan het gebruik van synchrone communicatie weer iets beter verantwoord worden dan asynchrone communicatie. Je ziet bij asynchrone communicatie vaak 1 thread die op meerdere resources ligt te slapen (zo`n resource kan bv een socket zijn). Zo gauw een van de resources iets heeft om te verwerken dan kan de thread wakker gemaakt worden en de info verwerken. Hierdoor ben je veel minder threads nodig dan bij synchrone communicatie (waar je dus een thread per resource hebt). Het probleem aan asynchrone communicatie is dat het vaak lastiger is om te programmeren dan synchrone communicatie. Maar aangezien de kosten van blokkerende threads toch minder hoog zijn, kan je wellicht toch vaker voor synchrone communicatie kiezen.

[ Voor 48% gewijzigd door Alarmnummer op 11-04-2006 13:07 ]


  • reddog33hummer
  • Registratie: Oktober 2001
  • Laatst online: 07-02 17:13

reddog33hummer

Dat schept mogelijkheden

Alarmnummer schreef op dinsdag 11 april 2006 @ 12:27:
Misschien ook leuk om te weten:
waar ik zelf bang voor was zijn grote hoeveelheden threads die liggen te slapen omdat ze een of andere kritieke sectie inwillen. Ik dacht dat de performance overhead voor het onnodig context swichten de andere processen behoorlijk kan beinvloeden. Maar moderne operating systems die kunnen uiteraard zien of een proces al weer kan draaien en zullen een proces ook niet gaan schedulen als het niet kan draaien (omdat het nog geblokkeerd is). Uiteraard heb je wel allerlei administratieve rompslomp, maar de kosten zijn een stuk minder hoog dan ik had gedacht.

Hierdoor kan het gebruik van synchrone communicatie weer iets beter verantwoord worden dan asynchrone communicatie. Je ziet bij asynchrone communicatie vaak 1 thread die op meerdere resources ligt te slapen (zo`n resource kan bv een socket zijn). Zo gauw een van de resources iets heeft om te verwerken dan kan de thread wakker gemaakt worden en de info verwerken. Hierdoor ben je veel minder threads nodig dan bij synchrone communicatie (waar je dus een thread per resource hebt). Het probleem aan asynchrone communicatie is dat het vaak lastiger is om te programmeren dan synchrone communicatie. Maar aangezien de kosten van blokkerende threads toch minder hoog zijn, kan je wellicht toch vaker voor synchrone communicatie kiezen.
Hiervoor heb je in .NET het verschil tussen worker threads en handling threads. Deze worden verschillend behandeld in het operating system. Java gebruikt light weight threads, dus dan is het anders.

Als je heel veel wachtende threads hebt, is het soms verstandig om een synchronized que te gebruiken.
Dan heb je verschillende threads die orders in de que zetten en paar die ze af wikkellen.
Dan kan je namelijk de threads in threadpools stoppen en hoeven ze niet te wachten.

Een voorbeeld is bijvoorbeeld een webserver. Je hebt dan een tread die een connectie aanneemd. Deze parst de request en zet de request in de que. en wordt dan weer toegevoegd aan de pool.
De verwerkerthread haalt uit de que het request, verwerkt hem en zet het resultaat in de "retour" que.
Een andere thread haalt deze uit de que en verstuurt die naar de client. Zodra hij klaar is gaat hij weer in de pool. Op die manier heb je geen Wachtende threads, omdat het wachten gedaan wordt door de que.

[ Voor 12% gewijzigd door reddog33hummer op 18-04-2006 09:39 ]

Backup not found (R)etry (A)bort (P)anic<br\>AMD 3400+ 64, 2 GB DDR, 1,5 TB Raid5


  • whoami
  • Registratie: December 2000
  • Laatst online: 15:46
Wat is een 'handling thread' als ik vragen mag ? Ik heb ff de MSDN bekeken, en gegoogled, maar nergens iets zinnigs gevonden over de term 'handling thread'.

https://fgheysels.github.io/


  • reddog33hummer
  • Registratie: Oktober 2001
  • Laatst online: 07-02 17:13

reddog33hummer

Dat schept mogelijkheden

whoami schreef op dinsdag 18 april 2006 @ 09:42:
Wat is een 'handling thread' als ik vragen mag ? Ik heb ff de MSDN bekeken, en gegoogled, maar nergens iets zinnigs gevonden over de term 'handling thread'.
Je moet bij asynchrone ASP.NET pagina's kijken.
Dezelfde zaken gaan voor "normale" pagina's ook een beetje op.

Handeling threads is niet de officiele naam. Normaal gebruik je hier ThreadPool threads voor omdat die kort leven en in het dotnet 2.0 platform 25 en 1.0/1.1 256 van zijn (standaard).
Deze threads waiten dus ook niet lekker door het .net platform omdat deze niet echt doorgegeven worden.

Threads gemaakt met de Thread classe zijn IO threads of worker threads. Deze worden verwacht langer gebruikt te worden. Het OS serialized deze ook als ze waiten en zijn dus efficienter in wachten op IO, maar wel trager.

Kijk in het .Net magazine Nr9 pagina 73 t/m 77 over normale aplicaties en 20 t/m 25 voor embedded aplicaties.

[ Voor 12% gewijzigd door reddog33hummer op 18-04-2006 10:38 ]

Backup not found (R)etry (A)bort (P)anic<br\>AMD 3400+ 64, 2 GB DDR, 1,5 TB Raid5


  • whoami
  • Registratie: December 2000
  • Laatst online: 15:46
De threads uit de threadpool zijn imho, afaik gewoon dezelfde threads als de Threads die je zelf creeërt.
De Threadpool is gewoon een pool met threads, die je toelaat om threads te 'hergebruiken' (vergelijk het met een connection-pool).
Het destroyen van een thread is duur.
Echter, als je een thread creeërt uit de thread-pool, en deze wordt nadien be-eindigd, dan keert hij terug naar de thread-pool, en wordt niet echt 'gesloten' (of hoe moet ik het zeggen. :P). Op die manier is het 'goedkoper' om threads uit de thread-pool te gebruiken.
When the CLR initializes, its thread pool contains no threads. When the application wants to create a thread to perform a task, the application should request the task be performed by a thread pool thread. The thread pool knows that and will create an initial thread. This new thread will go through the same initialization as any other thread; but, when the task is complete, the thread will not destroy itself. Instead, the thread will return to the thread pool in a suspended state. If the application makes another request of the thread pool, then the suspended thread will just wake up and perform the task and a new thread will not be created. This saves a lot of overhead. As long as the application queues tasks to the thread pool no faster than the one thread can handle each task, the same thread gets reused over and over again saving an enormous amount of overhead over the app's lifetime.
Now, you might be wondering what happens if the thread pool contains many threads and the workload on the application diminishes. In this case, the thread pool contains several threads that are sitting suspended for long periods of time, wasting OS resources. Microsoft thought about this, too. When a thread pool thread suspends itself, it waits for 40 seconds. If 40 seconds elapses and the thread is given nothing to do, then the thread wakes up and destroys itself, freeing all the OS resources (stack, kernel object, and so forth) that it was using. Also, it probably doesn't hurt performance to have the thread wake up and destroy itself because the application can't be doing too much anyway or the thread would have resumed execution. By the way though, I said that threads in the thread pool wake themselves up in 40 seconds, the actual amount of time is not documented and is subject to change.

https://fgheysels.github.io/


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

reddog33hummer schreef op dinsdag 18 april 2006 @ 09:35:
[...]

Hiervoor heb je in .NET het verschil tussen worker threads en handling threads. Deze worden verschillend behandeld in het operating system. Java gebruikt light weight threads, dus dan is het anders.

Als je heel veel wachtende threads hebt, is het soms verstandig om een synchronized que te gebruiken.
Dan heb je verschillende threads die orders in de que zetten en paar die ze af wikkellen.
Dan kan je namelijk de threads in threadpools stoppen en hoeven ze niet te wachten.
Daarvoor ben je nog steeds asynchrone communicatie nodig. Die thread die naar de set met connecties (op de sockets) loopt te luisteren, kan dit alleen doen als je asynchrone io tot je beschikking hebt
Een voorbeeld is bijvoorbeeld een webserver. Je hebt dan een tread die een connectie aanneemd. Deze parst de request en zet de request in de que. en wordt dan weer toegevoegd aan de pool.
De verwerkerthread haalt uit de que het request, verwerkt hem en zet het resultaat in de "retour" que.
Een andere thread haalt deze uit de que en verstuurt die naar de client. Zodra hij klaar is gaat hij weer in de pool. Op die manier heb je geen Wachtende threads, omdat het wachten gedaan wordt door de que.
Je hebt het wachten alleen verplaats. Eerst zaten ze te wachten op een socket (synchrone communicatie) en nu wachten ze op de queue.

En dit is een van de manieren waarop je nog redelijk eenvoudig met asynchrone communicatie om kunt gaan (ander manier is bv de leader/follower). Alleen asynchrone communicatie is veel minder intuitief dan synchrone communicatie en ik dacht dat synchrone communicatie enorme performance problemen met zich mee gaat brengen als je veel threads hebt (door al het context switchten), maar dat schijnt dus nog mee te vallen. Dat wil trouwens niet zeggen dat je altijd maar een synchrone oplossing moet kiezen, want bij een asynchrone oplossing heb je over veel dingen controle (bv een beperking op het aantal berichten in de queue zodat de server niet te veel werk voor de kiezen krijgt) een beperking op het aantal afhandelende threads (niet dat het systeem op zijn gat gaat omdat het te veel taken tegelijk probeerd af te handelen).

[ Voor 3% gewijzigd door Alarmnummer op 18-04-2006 11:00 ]


  • whoami
  • Registratie: December 2000
  • Laatst online: 15:46
Het OS serialized deze ook als ze waiten en zijn dus efficienter in wachten op IO, maar wel trager.
Hoezo dan ? De Thread class is niet serializeable.

https://fgheysels.github.io/


  • reddog33hummer
  • Registratie: Oktober 2001
  • Laatst online: 07-02 17:13

reddog33hummer

Dat schept mogelijkheden

whoami schreef op dinsdag 18 april 2006 @ 10:46:
De threads uit de threadpool zijn imho, afaik gewoon dezelfde threads als de Threads die je zelf creeërt.
De Threadpool is gewoon een pool met threads, die je toelaat om threads te 'hergebruiken' (vergelijk het met een connection-pool).
Het destroyen van een thread is duur.
Echter, als je een thread creeërt uit de thread-pool, en deze wordt nadien be-eindigd, dan keert hij terug naar de thread-pool, en wordt niet echt 'gesloten' (of hoe moet ik het zeggen. :P). Op die manier is het 'goedkoper' om threads uit de thread-pool te gebruiken.
Ga eens voor de grap kijken met de tools van http://www.systeminternals.com/. De .NET CLR gedraagt zich echt anders.

Backup not found (R)etry (A)bort (P)anic<br\>AMD 3400+ 64, 2 GB DDR, 1,5 TB Raid5


  • reddog33hummer
  • Registratie: Oktober 2001
  • Laatst online: 07-02 17:13

reddog33hummer

Dat schept mogelijkheden

whoami schreef op dinsdag 18 april 2006 @ 10:58:
Hoezo dan ? De Thread class is niet serializeable.
Niet geserializeerd als in binnen de .NET CLR.

De schedular van windows zelf kan sommige threads op de "Lange wacht" lijst zetten. Dan kunnen ze uitgepaged worden. Dit is een optimalisatie. In feite worden ze dan geserialized.

Backup not found (R)etry (A)bort (P)anic<br\>AMD 3400+ 64, 2 GB DDR, 1,5 TB Raid5


  • whoami
  • Registratie: December 2000
  • Laatst online: 15:46
reddog33hummer schreef op dinsdag 18 april 2006 @ 10:59:
[...]


Ga eens voor de grap kijken met de tools van http://www.systeminternals.com/. De .NET CLR gedraagt zich echt anders.
Nou, als ik al niet meer mag vertrouwen wat de MSDN en MSDN magazine me zegt...

https://fgheysels.github.io/


  • reddog33hummer
  • Registratie: Oktober 2001
  • Laatst online: 07-02 17:13

reddog33hummer

Dat schept mogelijkheden

Alarmnummer schreef op dinsdag 18 april 2006 @ 10:52:
Je hebt het wachten alleen verplaats. Eerst zaten ze te wachten op een socket (synchrone communicatie) en nu wachten ze op de queue.

En dit is een van de manieren waarop je nog redelijk eenvoudig met asynchrone communicatie om kunt gaan (ander manier is bv de leader/follower). Alleen asynchrone communicatie is veel minder intuitief dan synchrone communicatie en ik dacht dat synchrone communicatie enorme performance problemen met zich mee gaat brengen als je veel threads hebt (door al het context switchten), maar dat schijnt dus nog mee te vallen. Dat wil trouwens niet zeggen dat je altijd maar een synchrone oplossing moet kiezen, want bij een asynchrone oplossing heb je over veel dingen controle (bv een beperking op het aantal berichten in de queue zodat de server niet te veel werk voor de kiezen krijgt) een beperking op het aantal afhandelende threads (niet dat het systeem op zijn gat gaat omdat het te veel taken tegelijk probeerd af te handelen).
Je hebt het probleem alleen verplaatst als je machine niets te doen heeft (normaal weinig threads).
Maar dan is het geen probleem omdat het systeem dan toch "niets" doet.

Als je machine veel te doen heeft dan moeten threads wachten tot ze uitgevoerd kunnen worden. Dat is het wachten wat je tegen wil gaan. Omdat het afwerken van de requests (onder hoge load), geen wachten kent, kan 1 thread meerdere orders na elkaar uitvoeren en hoeft dus niet te wachten.

Backup not found (R)etry (A)bort (P)anic<br\>AMD 3400+ 64, 2 GB DDR, 1,5 TB Raid5


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024

Alarmnummer

-= Tja =-

reddog33hummer schreef op dinsdag 18 april 2006 @ 11:04:
[...]
Je hebt het probleem alleen verplaatst als je machine niets te doen heeft (normaal weinig threads).
Maar dan is het geen probleem omdat het systeem dan toch "niets" doet.
Mijn punt is niet goed overgekomen.

Ik dacht dat een systeem met veel threads die niets doen, veel overhead met zich mee zou brengen doordat het contextswitchen (het verwisselen van de running thread door de scheduler) niet gratis is.
Maar een scheduler kan zien of een thread runnable is, dus dan alleen gaat hij de thread inschedulen en anders niet. Uiteraard is het niet helemaal gratis: je bent uiteraard cpu tijd + geheugen nodig voor de administratie van die threads. Maar het grote punt van kritiek op synchrone communicatie (een thread per connectie) komt dus een klein beetje te vervallen.

  • reddog33hummer
  • Registratie: Oktober 2001
  • Laatst online: 07-02 17:13

reddog33hummer

Dat schept mogelijkheden

whoami schreef op dinsdag 18 april 2006 @ 11:01:
Nou, als ik al niet meer mag vertrouwen wat de MSDN en MSDN magazine me zegt...
Dot Net magazine issue 9 pagina 20 onderaan:
In 2.0 van het .NET Compact frameworkwordt de grotte van de pool teruggebracht naar 25, in overeenstemming met het .NET framework waardoor het wellicht belangrijker wordt ThreadPool-threads niet te gebruiken voor threads die de gehele levensduur van een applicatie beschikbaar moeten zijn.
Dus het wordt zoizo niet geadviseerd omdat je anders er zo doorheen bent. Nu kan je die pool groter maken.

pagina 73 rechtmiddenin:
In Windows 200 werdt voor het eerst een threadpool (schedgular gestuurd) geimplementeerd zodat threads via een poolmanager konden worden herbruikt.
De .NET CLR maakt gebruik van deze optimalizaties. Deze kan je met die tool bekijken.
Kijk ook eens voor de grap met de atached debugger naar de threadspaces.

Backup not found (R)etry (A)bort (P)anic<br\>AMD 3400+ 64, 2 GB DDR, 1,5 TB Raid5


  • reddog33hummer
  • Registratie: Oktober 2001
  • Laatst online: 07-02 17:13

reddog33hummer

Dat schept mogelijkheden

Alarmnummer schreef op dinsdag 18 april 2006 @ 11:09:
[...]

Mijn punt is niet goed overgekomen.

Ik dacht dat een systeem met veel threads die niets doen, veel overhead met zich mee zou brengen doordat het contextswitchen (het verwisselen van de running thread door de scheduler) niet gratis is.
Maar een scheduler kan zien of een thread runnable is, dus dan alleen gaat hij de thread inschedulen en anders niet. Uiteraard is het niet helemaal gratis: je bent uiteraard cpu tijd + geheugen nodig voor de administratie van die threads. Maar het grote punt van kritiek op synchrone communicatie (een thread per connectie) komt dus een klein beetje te vervallen.
Klopt, het is mischien goedkoper dan je dacht.
Maar alleen als je wait en interrupt gebruikt en geen yield en/of sleep (bussy wait).

Waar je wel mee uit moet kijken is dat als je heel veel threads hebt dat de schedular chache vol loopt en die gaat pagen (meer dan ~4000 threads) dan wordt de schedular traaaaaag. Dan is het verstandiger om de requests te gaan que'en.

Backup not found (R)etry (A)bort (P)anic<br\>AMD 3400+ 64, 2 GB DDR, 1,5 TB Raid5


  • whoami
  • Registratie: December 2000
  • Laatst online: 15:46
reddog33hummer schreef op dinsdag 18 april 2006 @ 11:16:
[...]

Dot Net magazine issue 9 pagina 20 onderaan:

[...]

Dus het wordt zoizo niet geadviseerd omdat je anders er zo doorheen bent. Nu kan je die pool groter maken.

pagina 73 rechtmiddenin:

[...]

De .NET CLR maakt gebruik van deze optimalizaties. Deze kan je met die tool bekijken.
Kijk ook eens voor de grap met de atached debugger naar de threadspaces.
Da's gewoon exact wat ik eerder vertelde: de pool bevat een aantal inactieve threads die kunnen her-gebruikt worden voor een andere taak. Echter, die threads zitten er niet voor altijd in.
Waar het over ging, is het verschil tussen worker - threads en 'handling' threads. Echter, dat verschil is er niet. Een Thread die uit de Threadpool gestart is, is gewoon hetzelfde als een thread die je zo start. Het verschil is dat die pool ervoor zorgt dat je evt sneller een thread object kunt krijgen, en, afaik zorgt de threadpool er ook voor dat je niet een 'onbeperkt' aantal threads op je server kunt laten lopen.

Het is gewoon zo dat er aangeraden wordt om de threadpool te gebruiken voor taken die je op een andere thread wilt uitvoeren, taken die niet lang duren, en waar je verder eigenlijk geen controle over nodig hebt. (Je bent bv ook niet zeker wanneer die thread precies gestart wordt, als het een thread-pool thread betreft, gewoon omdat de threadpool je request queuet, en je niet weet wanneer het exact uitgevoerd wordt:
Queues a method for execution. The method executes when a thread pool thread becomes available.

https://fgheysels.github.io/


  • reddog33hummer
  • Registratie: Oktober 2001
  • Laatst online: 07-02 17:13

reddog33hummer

Dat schept mogelijkheden

whoami schreef op dinsdag 18 april 2006 @ 11:26:
Da's gewoon exact wat ik eerder vertelde: de pool bevat een aantal inactieve threads die kunnen her-gebruikt worden voor een andere taak. Echter, die threads zitten er niet voor altijd in.
Waar het over ging, is het verschil tussen worker - threads en 'handling' threads. Echter, dat verschil is er niet. Een Thread die uit de Threadpool gestart is, is gewoon hetzelfde als een thread die je zo start. Het verschil is dat die pool ervoor zorgt dat je evt sneller een thread object kunt krijgen, en, afaik zorgt de threadpool er ook voor dat je niet een 'onbeperkt' aantal threads op je server kunt laten lopen.
Nee, het is niet hetzelfde.
Ja, het is zo dat doordat de threadpool gebruikt wordt je gewoon sneller een thread krijgt en hergebruikt worden.

Alleen aan de achterkant gebeuren er nog meer dingen. De CLR is namelijk geoptimaliseerd.
Daarom worden Threads die geen onderdeel uitmaken van een threadpool anders behandeld, omdat er van uitgegaan wordt dat die langer blijven leven.

Dat is namelijk ook een probleem met mensen die uit java komen en in Jsharp threads gan gebruiken. Java in de jvm maakt gebruik van light weight threads. De Jsharp java.lang.Thread classe is alleen de een zware (nog niet eens een geerfte classe van) System.Threading.Thread. Daarom zijn Thread van java.lang.Thread zo traag onde JSharp.

Backup not found (R)etry (A)bort (P)anic<br\>AMD 3400+ 64, 2 GB DDR, 1,5 TB Raid5


  • whoami
  • Registratie: December 2000
  • Laatst online: 15:46
Tja, wie heeft het over java.lang.Thread. Die worden afaik ook helemaal niet door de .NET threadpool behandeld.

Het enige verschil tussen een threadpool-thread en een gewone thread is afaik het feit dat een threadpool-thread een background thread is (IsBackGroundThread property).

https://fgheysels.github.io/


  • reddog33hummer
  • Registratie: Oktober 2001
  • Laatst online: 07-02 17:13

reddog33hummer

Dat schept mogelijkheden

whoami schreef op dinsdag 18 april 2006 @ 11:46:
Het enige verschil tussen een threadpool-thread en een gewone thread is afaik het feit dat een threadpool-thread een background thread is (IsBackGroundThread property).
Nee dat zijn ze niet (pagina 20 rechts, onderaan, heerlijk die magazines).

Maar dat kan je ze wel maken.

Wel is het zo dat als ze in de threadpool zitten, die threads "niet bestaan" en daardoor het programma niet open houden.

[ Voor 14% gewijzigd door reddog33hummer op 18-04-2006 12:00 ]

Backup not found (R)etry (A)bort (P)anic<br\>AMD 3400+ 64, 2 GB DDR, 1,5 TB Raid5


  • whoami
  • Registratie: December 2000
  • Laatst online: 15:46
Wel is het zo dat als ze in de threadpool zitten, die threads "niet bestaan" en daardoor het programma niet open houden.
Dat komt gewoon omdat het background-threads zijn.
The difference between a background thread and a foreground thread is pretty simple. When the last foreground thread of a process is stopped, then the process terminates. There could be zero, 1 or an infinite number of background threads and they have no vote in whether a process terminates or not. So when the last foreground thread stops, then all background threads are also stopped and the process is stopped.

[ Voor 54% gewijzigd door whoami op 18-04-2006 12:13 ]

https://fgheysels.github.io/


  • whoami
  • Registratie: December 2000
  • Laatst online: 15:46
reddog33hummer schreef op dinsdag 18 april 2006 @ 11:58:
[...]

Nee dat zijn ze niet (pagina 20 rechts, onderaan, heerlijk die magazines).
Thread Pool Characteristics

Thread pool threads are background threads. See Foreground and Background Threads. Each thread uses the default stack size, runs at the default priority, and is in the multithreaded apartment.
Nee dat zijn ze niet (pagina 20 rechts, onderaan, heerlijk die magazines).
Je kan nu wel blijven naar dat .NET magazine verwijzen, als ik het hier niet liggen heb, dan kan ik het ook niet bekijken.
Ik zal vanavond het betreffende artikel in het .NET magazine daarover opzoeken.

[ Voor 26% gewijzigd door whoami op 18-04-2006 12:15 ]

https://fgheysels.github.io/


  • reddog33hummer
  • Registratie: Oktober 2001
  • Laatst online: 07-02 17:13

reddog33hummer

Dat schept mogelijkheden

whoami schreef op dinsdag 18 april 2006 @ 12:14:
Thread pool threads are background threads. See Foreground and Background Threads. Each thread uses the default stack size, runs at the default priority, and is in the multithreaded apartment.
[...]
Je kan nu wel blijven naar dat .NET magazine verwijzen, als ik het hier niet liggen heb, dan kan ik het ook niet bekijken.
Ik zal vanavond het betreffende artikel in het .NET magazine daarover opzoeken.
Ze zijn background threads als ze niet actief zijn. anders zijn het gewoon foreground threads.

Backup not found (R)etry (A)bort (P)anic<br\>AMD 3400+ 64, 2 GB DDR, 1,5 TB Raid5


  • whoami
  • Registratie: December 2000
  • Laatst online: 15:46
reddog33hummer schreef op dinsdag 18 april 2006 @ 12:28:
[...]

Ze zijn background threads als ze niet actief zijn. anders zijn het gewoon foreground threads.
Nee.
Een background-thread is een thread die, ook al runt hij, gestopt wordt als de applicatie gestopt wordt.
Sla er de MSDN eens op na:
A thread is either a background thread or a foreground thread. Background threads are identical to foreground threads, except that background threads do not prevent a process from terminating. Once all foreground threads belonging to a process have terminated, the common language runtime ends the process by invoking Abort on any background threads that are still alive.

https://fgheysels.github.io/


Verwijderd

Uit het artikel in .NET Magazine #9, pag 20. leid ik niet af dat ThreadPool threads en gewone threads verschillende threads zouden zijn. Het gebruik is alleen anders.

Overigens gaat het artikel over het .NET Compact Framework.

  • reddog33hummer
  • Registratie: Oktober 2001
  • Laatst online: 07-02 17:13

reddog33hummer

Dat schept mogelijkheden

Sorry. Je hebt gelijk. Dat geld alleen voor het compact framework.
code:
1
2
3
4
5
6
7
8
9
10
        [STAThread]
        static void Main(string[] args)
        {   
            ThreadPool.QueueUserWorkItem(new WaitCallback(CountThread));            
        }

        public static void CountThread(Object x)
        {
            Console.WriteLine(Thread.CurrentThread.IsBackground);
        }

geeft inderdaad true.
Maar kijk wel even met de sysinternals tools, want de clr gedraagt zich echt wel anders.

[ Voor 12% gewijzigd door reddog33hummer op 18-04-2006 13:45 ]

Backup not found (R)etry (A)bort (P)anic<br\>AMD 3400+ 64, 2 GB DDR, 1,5 TB Raid5

Pagina: 1