Delphi TParallel.for比经典慢

ar0*_*968 1 delphi asynchronous

我需要填充TJsonArray很多TJsonObjectTJsonArray并且TJsonObject来自JsonDataObjects)。我正在尝试TParallel.For()从本System.Threading机提高性能,但是我TParallel.For()的速度比经典for循环慢。

这是我的测试代码:

var
  aLock:  TCriticalSection;
  jItems: TJsonArray;
  jItem:  TJsonObject;
  aStart: Cardinal;
  aEnd:   Cardinal;
  i:      integer;
begin
  // array of json objects
  jItems  := TJsonArray.Create;

  // ASYNC FOR LOOP
  // ----------------------------
  aLock  := TCriticalSection.Create;
  aStart := GetTickCount;
  TParallel.&For(0, 10000000,
    procedure(k: Integer)
    var
      xItem: TJsonObject;
    begin
      aLock.Enter;
      try
        // add new object to the array
        xItem := jItems.AddObject;
      finally
        aLock.Leave;
      end;
      // populate some object property for test
      xItem.I['I'] := k; // .I for integer
      xItem.F['F'] := k; // .F for float
      xItem.S['S'] := IntToStr(k); // .S for string
      xItem.D['D'] := Now; // .D for date
    end
  );
  aEnd := GetTickCount;
  Writeln('ASYNC ', aEnd-aStart);
  // ----------------------------

  aLock.Free;
  jItems.Clear;

  // SYNC FOR LOOP
  // ----------------------------
  aStart := GetTickCount;
  for i := 0 to 10000000 do begin
    jItem := jItems.AddObject;
    jItem.I['I'] := i;
    jItem.F['F'] := i;
    jItem.S['S'] := IntToStr(i);
    jItem.D['D'] := Now;
  end;
  aEnd := GetTickCount;
  Writeln('SYNC ', aEnd-aStart);
  // ----------------------------

  jItems.Free;
end;
Run Code Online (Sandbox Code Playgroud)

这是结果(数字是经过的时间(以毫秒为单位)):

图片

我认为我的TParallel.For()实现是错误的。我究竟做错了什么?

Rem*_*eau 6

正如其他人提到的那样,您在TJsonArray序列化周围使用关键部分会使线程线程化,并且可能是主要的瓶颈。尝试摆脱关键部分,在进入循环之前预先分配阵列,然后让每次循环迭代都根据需要简单地填充阵列的现有插槽。这样,您就更有机会同时并行地将多个对象插入到阵列中。

var
  jItems: TJsonArray;
  jItem:  TJsonObject;
  aStart: Cardinal;
  aEnd:   Cardinal;
  i:      integer;
begin
  // array of json objects
  jItems  := TJsonArray.Create;

  // ASYNC FOR LOOP
  // ----------------------------
  jItems.Count := 10000001; // <-- add this!
  aStart := GetTickCount;
  TParallel.&For(0, 10000000,
    procedure(k: Integer)
    var
      xItem: TJsonObject;
    begin

      // create new object
      xItem := TJsonObject.Create;

      // populate some object property for test
      xItem.I['I'] := k; // .I for integer
      xItem.F['F'] := k; // .F for float
      xItem.S['S'] := IntToStr(k); // .S for string
      xItem.D['D'] := Now; // .D for date

      // add new object to the array
      jItems.O[k] := xItem;
    end
  );
  aEnd := GetTickCount;
  Writeln('ASYNC ', aEnd-aStart);
  // ----------------------------

  jItems.Clear;

  // SYNC FOR LOOP
  // ----------------------------
  aStart := GetTickCount;
  for i := 0 to 10000000 do begin
    jItem := jItems.AddObject;
    jItem.I['I'] := i;
    jItem.F['F'] := i;
    jItem.S['S'] := IntToStr(i);
    jItem.D['D'] := Now;
  end;
  aEnd := GetTickCount;
  Writeln('SYNC ', aEnd-aStart);
  // ----------------------------

  jItems.Free;
end;
Run Code Online (Sandbox Code Playgroud)