Results 1 to 9 of 9

Thread: RANT: TThreadPool.Min/Max workers

  1. #1

    RANT: TThreadPool.Min/Max workers

    Arg, arg, arg. Ik wil een load-test programmatje maken, en daarvoor wil ik graag maximaal 3 threads tegelijk gebruiken.
    Er is een mooie abstractie voor het uitvoeren van een parallelle taak: TTask.
    Die taak wordt uitgevoerd door een TThreadPool. Ook mooi. Die heeft properties waarmee je kan instellen hoeveel worker threads deze mag hebben, en DAT WERKT NIET.

    Waarom? Omdat één of ander helder licht bedacht heeft dat je niet minder workers mag hebben dan processors (waarom?!) en dat MinWorkers kleiner moet zijn dan (en dus niet gelijk aan) MaxWorkers. WAAROM?!!

    Het is mijn ThreadPool. Als ik precies 3 workers wil dan is dat toch mijn zaak?

    Delphi Code:
    1. function TThreadPool.SetMaxWorkerThreads(Value: Integer): Boolean;
    2. begin
    3.   Result := Value >= TThread.ProcessorCount;
    4.   if Result then
    5.     TInterlocked.Exchange(FMaxLimitWorkerThreadCount, Value);
    6. end;
    7.  
    8. function TThreadPool.SetMinWorkerThreads(Value: Integer): Boolean;
    9. begin
    10.   Result := (Value > -1) and (Value < FMaxLimitWorkerThreadCount);
    11.   if Result then
    12.     TInterlocked.Exchange(FMinLimitWorkerThreadCount, Value);
    13. end;
    Last edited by GolezTrol; 10-May-18 at 15:44.
    1+1=b

  2. #2
    En ja, er is een 'oplossing':

    Delphi Code:
    1. while ThreadCount >= 3 do
    2.   Sleep(0);
    3.  
    4. TInterlocked.Increment(ThreadCount);
    5. try
    6.  
    7.   // Het echte werk gebeurt hier
    8.  
    9. finally
    10.   TInterlocked.Decrement(ThreadCount);
    11. end;
    Last edited by GolezTrol; 01-May-18 at 23:13.
    1+1=b

  3. #3
    Stijn Sanders develyoy's Avatar
    Join Date
    Jun 2008
    Location
    GentBrugge, Belgi?½
    Posts
    1,046
    Of zelf TThread overerven, en er 3 van starten.

  4. #4
    Nou, zo simpel is het niet. Ik moet namelijk tientallen threads starten, maar ik wil dat er maar 3 tegelijk lopen. De reden is dat ik een tooltje heb gemaakt om een API te kunnen stress testen, en ik wil X aantal requests in parallel afvuren op die API om te kijken of de waarde van X nog effect heeft op de duur van de call. TThreadPool zou daar een mooi mechanisme voor kunnen zijn, maar ik word dus weer eens beperkt door een m.i. volkomen onnodige kunstmatige beperking. Het zou voor die TThreadPool niet uit moeten maken hoeveel workers hij heeft. Dat het initieel het aantal processors is, soit, maar waarom kan ik daar niet onder gaan zitten?

    Ik kan het natuurlijk ook zelf bouwen (zelfs al eens gedaan), maar het frustreert me gewoon dat er nog steeds dit soort ondoordachte dingen aan de VCL toegevoegd worden.
    1+1=b

  5. #5
    Stijn Sanders develyoy's Avatar
    Join Date
    Jun 2008
    Location
    GentBrugge, Belgi?½
    Posts
    1,046
    Het is misschien wat vergezocht, maar ik zou het dan eens proberen met 3 CreateEvent handles and WaitForMultipleObject. Bij de eerste krijg je zo te horen welke van de 3 handles 'vrij' zijn, en bij meer dan 3 wachtende threads, gaat het systeem zelf beslissen welke van de wachtende eerste horen krijgt dat er eentje vrij komt. Wel na het uitvoeren van een taak ResetEvent doen natuurlijk om te laten weten dat de thread klaar is.

  6. #6
    Bedankt voor de hulp Stijn, maar m'n post was eigenlijk niet zozeer bedoeld als vraag dan wel als klacht. Er zijn inderdaad allerlei manieren om het (met meer werk en/of minder elegant) op te lossen.

    Overigens is het afvuren van meerdere taken en het wachten daarop ook wel geïmplementeerd in TTask. Je kan dus meerdere taken maken, die per 3 in een array stoppen en dan WaitForMultiple aanroepen om te wachten tot ze klaar zijn.
    1+1=b

  7. #7

    We hebben allebei deze bug net 9 dagen uit elkaar ontdekt!

    Excuses dat ik Google Translate gebruik

    https://quality.embarcadero.com/browse/RSP-20528

    You have to setMaxWorkerThreads BEFORE setMinWorkerThreads to work around the second bug not yet logged.

  8. #8
    Bedankt voor de tip! Als je in de code kijkt, dan zou dat inderdaad kunnen werken. Je moet dan eerst Max zetten, daarna Min, en daarna Max verlagen:

    Delphi Code:
    1. SetMaxWorkerThreads(11);
    2. SetMinWorkerThreads(10);
    3. SetMaxWorkerThreads(10);

    Helaas lukt het dan nog steeds niet om het aantal threads te verlagen tot minder dan het aantal processors.
    1+1=b

  9. #9
    Comment out this in System.Threading, add System.Threading (the full .pas path) to your project and rebuild

    function TThreadPool.ShouldGrowPool: Boolean;
    begin
    Result := {(FWorkerThreadCount < FMinLimitWorkerThreadCount) and } (FIdleWorkerThreadCount < FQueuedRequestCount) and
    (FWorkerThreadCount < Self.FMaxLimitWorkerThreadCount);
    end;

    Do the same to apply your edit to the RTL unless you are using packages.

    All of these issues have been logged to https://quality.embarcadero.com/browse/RSP-20533

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •