21. juli 2006 - 14:33Der er
16 kommentarer og 2 løsninger
Egen ThreadPool
Noget jeg har sidet og kigget på i et længere stykke tid nu er at lave ens egen ThreadPool klasse... Specielt en der egner sig til lange opgaver (opgaver der tager flere minutter, men stadig kan være et par 100 stykker af)....
Jeg har så fundet 2 eksempler på nettet... en i VB.NET... og en i C# fra noget developmentor.... Den sidste virker lidt som det bedste bud... men den er meget svær at overskue sådan lige fra starten... selv for en meget erfaren programmør...
Desuden er den som jeg umiddelbart kan se det, lavet til korte jobs... eller dvs. jobs der udføres fuldt...
Det jeg gerne vil er at lave en hvor jeg kan give en given thread en tid at arbejde i og så pille den ud og bag i køen...
Lad os fx sige at man PT har 100 tråde, og man tillader 20 tråde at kører sideløbende...
Så smider man 1-20 ind til at starte med... og implementere en måde at overvåge deres "arbedstid"... når der så fx er gået 10ms for dem hver i sær pilles de ud og tråd 21-40 kommer ind...
Det er naturligvis en firkantet måde at se det på... og det bliver jo også mere advanceret end det.... først og fremmes tager det tid at starte dem hver i sær jo... dermed startes de jo ikke alle til tiden 0... dernest smides de også løbende ind i thread pool'en...
Derfor vil et scenarie hvor fx de første 20 tråde PT er i kø... nu overskrider Tråd 1 så sin givne tid... og pilles derfor ud af de kørende tråde... tråd 21 kommer ind... lidt sennere overskrider tråd 2... tråd 22 kommer ind...
Nu sker der det at tråd 10 afslutter efter 8ms inde... da den er færdig med at afvikle det den skulle... tråd 23 kommer ind...
OSV... altså noget alla RR implementeret på Applications niveau... Med den twist at man lader styrersystemets trådmodel styre X antal tråde.. (i eksemplet her 20 stk)...
Senere kan man så kigge på implementeringen af andre algoritmer...
Men hvordan skal man så lige gøre dette... dette ville jeg gerne have nogle gode bud på... nogle fornuftige links osv...
Denne side indeholder artikler med forskellige perspektiver på Identity & Access Management i private og offentlige organisationer. Artiklerne behandler aktuelle IAM-emner og leveres af producenter, rådgivere og implementeringspartnere.
Så kører de jo stadig... Og belastningen knækker stadig... for selv om der er forskellig prioritet, så prøver fx 200 tråde jo stadig at få lov... forskellen er jo bare at 20 af dem får mere lov end andre... men de andre bliver stadig kørt... hvis der findes plads til det...
Det jeg vil sikre mig, er at jeg har 20 eller et andet antal Tråde i min pool... og ikke mere...
Ganske som man med alle andre ThreadPools bliver det jo så ikke en thread jeg enqueueer men et arbejde...
Men i forhold til de andre ThreadPools jeg har set, så hvis man smider 200 jobs in... som hver tager lad os sige 5 min... så udfører den 1-20 fuldt først...
Dette går ikke for mig...
Jeg vil sikre mig det samme som med alm. Thread pools... men samtidig sikre mig at hver job får fx 10 ms... hvis det så ikke er færdig... så skal en given algoritme styrer hvornår det så kommer for igen....
Det kunne jo fx være RR hvor det bare bliver smidt bag i en kø igen... og venter til alle andre jobs har fået lov at kører i 10 ms... det kunne være en speciel form for Prioriteret RR, hvor høj prioritet bliver udført først... det kunne også være sådan at høj prooritet bare får mere tid tildelt..
Endelig kunne det foregå via sporatic... dvs lidt ala det du foreslår... dog skal de stadig ikke have lov til at "prøve" på at få arbejde... det er noget jeg vil styrer fra min klasse... ikke lade det underliggende styrer...
pointen er at man så hver gang man laver en app hvor man ender med disse lange arbejdsopgaver... og mange af dem sideløbende... så behøver man ikke bekymre sig om at splitte opgaverne op i små bider... for det er netop det denne ThreadPool gerne skulle "gøre" for en...
Flexibilitet er kodeordet her... da jeg vil lade folk selv vælge en algoritme hvorfra jobs bliver valgt... Eller måske enda kode egne scheduleringer...
Jeg har lavet noget lignende. Vi har sådan nogle regler om en tråd ikke må starte før et antal andre er færdige. Jeg bruge AutoResetEvent og ManualResetEvent til at styre hvornår de forskellige ting var færdig.
Sådan skal det her ikke fungere... netop her må en de gerne alle starte... de må bare ikke alle være aktive på samme tid...
Skulle køre sådan at
20 tråde, 5 max aktive:
0-10 ms Tråd 1-5 Aktiv Tråd 6-20 Inaktiv
10-20 ms Tråd 1-5 Inaktiv Tråd 6-10 Aktiv Tråd 11-20 Inaktiv
20-30 ms Tråd 1-10 Inaktiv Tråd 11-15 Aktiv Tråd 16-20 Inaktiv
30-40 ms Tråd 1-5 Aktiv Tråd 6-20 Inaktiv...
Osv...
Principet er 100% det samme som når et OS schedulere threads osv... bortset fra at man her "lader" som om at man kan udføre X Threads på samme tid... Blandt den mængde er det så derfra OS'ets opgave at styrer hvilken af disse der har Processoren på hvilket tidspuknt ud fra dens egen scheduling...
Skal se om jeg ikke kan lave en slags skitse for at gøre det mere klart...
Det her er forholdsvis korte opgaver i forhold til det jeg siger efter... vi taler om opgaver der tager ~50-150 ms... de opgaver jeg gerne vil kunne arbejde med også... kan varer fra 5 min - 30 min gennemsnitlig... men opgaver op imod 5-10 timer kan sikkert også komme på tale... hvertfald skal den kunne arbejde med disse også....
Skitsen har kun 20 Opgaver som enques inden for relativ kort tid... reælt vil der kunne komme et kontinuerligt flow af opgaver op imod en 200 stk måske....
Ok kan godt se hvor du vil hen nu. Tror du skal gøre som arne skriver have en tråd til at styre din pool. Lav en timer der der ved hver udløb udfører det regelsæt du selv har sat op. Du skal bare tænke dig lidt om når du kalder Suspend() på en tråd det kan skabe lidt problemer hvis du udføres på de forkerte ting.
Men i bund og grund lav et array med dine tråde, lad en super tråd stå og starte og stoppe de givne tråde.
segato >> Ja jeg er godt klar over jeg skal have en supevisor tråd osv... det havde jeg også i forvejen, det jeg ikke er så vild med er netop Suspend(), som jo desuden også er depricated af en grund...
Men der er jo nok ikke nogen vej uden om i mit specifikke tilfælde... Havde jeg bare lidt håbet der var...
Jeg har så nok en plan om at implementere det sådan at man ved oprettelsen af threadpolen kan definere hvor strict den skal fungere, og så give muligheden for at "låse" en tråd... forstået på den måde at man kan signalere op at man er i en kritisk blok og helst gerne vil ud af denne før man bliver Suspended...
Det er også typisk en blok man beskytter med lock eller monitor, men så vidt jeg ved, så blokere det jo kun for adgang for andre tråde, men tillader jo stadig at tråden bliver suspended... hvilket jo kan give deadlocks...
Muligheden man så har er at kalde op at nu er man i en block hvor man helst vil ud af før man bliver suspended, så vil Threadpoolen i det en tråds tidstildeling udløber, give tråden lidt extra tid for at se om den nu ikke kunne komme ud af den blok...
I det den så træder ud af den blok, suspendes den med det samme, gør den ikke inden for den givne extra periode den har fået, så bliver den "Force suspended"... dvs. at man Suspender den regardless...
(Det er også det der vil ske uanset hvad hvis man vælger en Strict Threadpool)...
Det overlader lidt extra arbejde til programmøren, men jeg kan ikke lige se hvad man ellers kan gøre... (Nogle andre briliante ideer???)
Indtil videre sender jeg KaldeObjectet med ned i tråden... Men jeg ved ikke om det kan gøres anderledes (Mere elegant?)...
Nogen ideer til hvordan dette implementeres bedst?
Suspend ville jeg heller ikke bryde mig om den er roden til alt ondt. Personligt ville jeg gore den anden vej rundt. Jeg ville ikke have en supervosior til at styre, men i stedet lade traadene bestemme hvornaar de er fardig og saa signallere til din supersisor at nu er jeg faerdig. Og jeg ville signalere via AutoResetEvent. Din supervisor staar saa i en vente tilstand og venter paa traadene er fardige og naar den bliver signalleret starter den saa nye traade op.
Det kan ikke komme til at du, trådene signalere naturligvis allerede når de er færdige, men de må ikke have ansvaret for at tildele sig selv tid... derfor duer det ikke at det er dem der også står for at holde pauser, det bliver supervisor tråden nød til at stå for
Problemmet er bare du kan risikere at suspende på et mildest talt meget uheldigt tidspunkt. Midt i en database operation, eller fil skrivning osv osv. Dette kan du jo risikere at have fatale konsekvenser. Så i stedet kunne man på et given tidspunkt sige til en tråd "gå i pause så hurtigt som muligt", hvilket f.eks. ville bryde ne løkke osv osv. og så melder tråden tilbage om nå er den i pause mode. Sådan har jeg selv lavet et system på mit arbejde. Men har du ikke den luksus er der jo kun suspend tilbage og så er detjo bare svaret.
Jeg er godt klar over at man kan få den suspenderet på et uheldigt tidspunkt og i værste fald skabe deadlocks...
Af netop samme grund skulle man have muligheden for at signalere at "nu er jeg i en kritisk blok, suspender mig ikke", i selv samme stil som du kalder lock(noget) eller Monitor.enter... for det må være programørens ansvar at låse i deisse tilfælde...
Hvis der ikke gøres noget her, må man gå ud fra at tråden ikke har noget der kan kvalificeres som kritisk arbejde, og ja så suspenderes den bare...
Men der er det så at dette i mit tilfælde heller ikke må "misbruges", eller man skal hvertfald have muligheden for at sige at det ikke kan, for ellers kunne man bare låse tråden ved enter, og låse op ved exit...
Det skaber den uheldige virkning i mit tilfælde at jeg ligesågodt kunne lade være med at have min threadpool, da en tråd pluselig vil låsesig til arbejde i op imod 30 min... det var netop dette scenarie der skulle undgåes...
Derfor bliver der opsætning for hvor strict den kan køres, hvor det højeste niveau er komplet ligeglad med hvor vidt man er i en kritisk blok... (lidt ligsom PLC'er er ligeglad med om kode har eksekveret)...
Det laveste niveau er naturligvis extrem flink og lader trådene kører til de ikke er låst, mens et eller flere niveauer i midten lader tråde kører maximalt et en given tid over deres deadline...
Pointen er så...
Tråd X startes Tråd X Kører i 3 ms Tråd X Kræver en lås Tråd X kører yderligere 7 ms Tråd X bliver bedt om at suspendere og returnere false fordi den er låst Tråd X får mere tid og kører 2 ms mere Tråd X åbner sin lås Tråd X bliver straks suspenderet fordi den er over sin timeslide
Dette kunne være et af de mest alm. scenarier... så det er jo også meget lig det du nævner med "gå i pause hurtigst muligt"... men man har så muligheden for at sætte højeste stricthed... så ville det se ud som:
Tråd X startes Tråd X Kører i 3 ms Tråd X Kræver en lås Tråd X kører yderligere 7 ms Tråd X bliver bedt om at suspendere og returnere false fordi den er låst Tråd X bliver tvunget til at suspendere grundet højeste stricthed Tråd X skaber formentlig her en deadlock...
Det kan se ud som om at dette er ret risikabelt, men typisk vil sådan en høj stricthed kun anvendes inden for opgaver hvor man ved med 100% sikkerhed hvor lang tid de vare, eller at de ikke kan gå i deadlocks...
og der skal man nok have beskæftiget sig med nogle sådanne opgaver for at se anvendeligheden.
Ja man skal ikke slå mange hjerne fiser før det går galt. Og det er et ganske kompliceret scenario du har sat op, men det gør det jo bare det mere spændende :D
True true... desvære har jeg meget ringe tid til det for tiden med arbejde og sådan... så begynder snart at tænke på om det nogen sinde bliver til mere end det er nu... men well...
Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.