RepeatUntil
RepeatUntil

Reputation: 2320

TTask slower than TThread

I have below two methods of multi-threading code doing the same job.

TTask:

const
  MaxThreadCount = 80;

procedure TWorkerTask.Update;
var
  aTasks  : array of ITask;
  I: Integer;
begin
  Stopwatch := TStopwatch.StartNew;
  SetLength(aTasks, MaxThreadCount);
  for I := Low(aTasks) to High(aTasks) do begin
    aTasks[I] := TTask.Create( procedure
    begin
      Writeln('Thread ', TTask.CurrentTask.Id, ' Stared');
      Sleep(5000);
      Writeln('Thread ', TTask.CurrentTask.Id, ' Finshed');
    end);
    aTasks[I].Start;
  end;
  TTask.WaitForAll(aTasks);
  Elapsed := Stopwatch.Elapsed;
  Writeln('Done in ', Round(Elapsed.TotalSeconds));
end;

Output e.g Done in 29

TThread:

const
  MaxThreadCount = 80;

procedure TWorker.Execute;
begin
  Writeln('Thread ', ThreadID, ' Stared');
  Sleep(5000);
  Writeln('Thread ', ThreadID, ' Finshed');
end;

....

var
  Workers   : array of TWorker;
  I         : Integer;
  Stopwatch : TStopwatch;
  Elapsed   : TTimeSpan;  
begin
  SetLength(Workers, MaxThreadCount);
  for I := Low(Workers) to High(Workers) do begin
    Workers[I] := TWorker.Create;
    Workers[I].Start;
  end;
  for I := Low(Workers) to High(Workers) do
    Workers[I].WaitFor;
  Elapsed := Stopwatch.Elapsed;
  Writeln('Done ', Round(Elapsed.TotalSeconds));

Output e.g Done 8

Q: Why the TTask is extremely slower than the TThread class on the above method? Is there a way to speed it up to get similar result?

Upvotes: 4

Views: 2511

Answers (2)

viniciusfbb
viniciusfbb

Reputation: 681

Each task does not necessarily mean 1 thread. The delphi tasks system saves resources, and even monitors CPU usage to decide whether to create more threads or not. Particularly I also find the task slow, and to avoid this slowness, when I need to use task I simply create a threadpool for each task, so it will have the same performance as a simple TThread because that way you will ensure that each task will run on own thread.

You can try something like this:

TTask.Run(
  procedure()
  begin
  end, TThreadPool.Create);

Upvotes: 0

David Heffernan
David Heffernan

Reputation: 612794

It's because your threads and tasks do no work.

You have more threads than processors. In the version using threads, you can create one thread per task and although the processors are oversubscribed, that doesn't matter because the threads are sleeping.

In the task based version there is, typically, one thread per processor. So not all tasks can run simultaneously.

Were you to replace the sleep with busy work running the CPU at full utilisation then you would see that both versions performed similarly. Indeed I would expect the task based version to be better since it would not oversubscribe the processors.

Upvotes: 8

Related Questions