我需要填充TJsonArray
很多TJsonObject
(TJsonArray
并且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;
这是结果(数字是经过的时间(以毫秒为单位)):
我认为我的TParallel.For()
实现是错误的。我究竟做错了什么?
正如其他人提到的那样,您在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;