Tlist删除技巧
二、????從TList開始分析……
為了寫一個更好的性能ISAPI Filter,我需要更快速地從TList中刪除部分連續的Item。比如這樣的一段代碼:
var p : pChar = 'abcdefgh'; procedure TestDelFromTList; var t1 : TList; ??? i? : integer; ??? maxI : integer; begin ? t1 := tlist.create; ? t1.count := 100000; ? for i:=0 to t1.count-1 do t1[i] := p; ? maxI := t1.count-10-1; //最后一個結點 ? for i:= maxI downto 10 do t1.delete(i); ? //正向刪除 ? //for i:=10 to t2.count-10-1 do t2.delete(10); end;這段代碼是初始化一個100000個結點的List,然后刪除其中的第10個到倒數第10個。這段代碼是逆向的,這樣的刪除速度比較快。如果換成正向刪除(已經注釋掉),則速度就慢得非常多了。
這樣的刪除是正常的算法。用測效率的程序測試:逆向刪除算法的耗時是21.66個毫秒,則正向刪除的耗時卻能達到58099.02個毫秒。速度慢了2680倍!!!
但這樣就很快了么?不是!我認為就算是逆向刪除的速度也并不是快的。
分析TList這個類的源碼,我們可以看到,它是這樣寫的(我加入了注釋):
procedure TList.Delete(Index: Integer); var ? Temp: Pointer; begin if (Index < 0) or (Index >= FCount) then //判定Index值是否超界 Error(@SListIndexError, Index); ? Temp := Items[Index];?????????????????????? ?//取待刪除結點 ? Dec(FCount); ??????????????????????????????????//Count減一 if Index < FCount then?????????????????????? //將待刪除結點后的Buffer提前 System.Move(FList^[Index + 1], FList^[Index],(FCount - Index) * SizeOf(Pointer)); if Temp <> nil then?????????????????????????? //發通告 Notify(Temp, lnDeleted); end;由于在TList類是將全部的結點指針存放在FList這個動態數組的指針中,所以只需要將Index+1之后的內存塊向前移4個字節,即SizeOf(Pointer),即可實現Index結點的刪除。
但是,如果使用這樣來刪除成批連續的(N個)結點,則要實現N次system.move()操作,操作的內存塊的大小決定了system.move()操作的耗時,而Index值越小的的結點在FList中越靠前,則system.move()要操作的內存塊也就越大。這就是我認為上述成批刪除效率不高的原因,也是正向刪除比逆向刪除的耗時慢了慢了2680倍的原因。
對于成批刪除,理想的算法是從index+len結點開始位置,向前移動count-index-len個結點,這樣,就能夠一次完成全部的結點移動,實現刪除操作。這個思路非常好,至少我認為是這樣。為此,我實現了下面的代碼:
procedure CutList(aList:TList; left,len:integer); begin ? with aList do begin System.Move(List^[left+len], List^[left], (Count-left-len) * SizeOf(Pointer)); ??? count := count-len; ? end; end;這段代碼的功能是在TList.List這個Buffer中,將刪除后的剩余結點直接移動到Left這個位置上,從而完成全部的移動操作。
然后,我們再設count := count-len;來使用個數減少,從而完成了成批量的刪除。
好的,如果一切正常,算法的速度將大幅度提升!OHHH,美妙的想法!
但是,真的是這樣么?我再用效率測試程序來測試了一輪,結果是這樣的:
1.????測試數據為10萬個結點,則逆向刪除算法耗時為20.56毫秒,CutList()函數耗時9.69毫秒;
2.????測試數據為100萬個結點,則逆向刪除算法耗時為209.13毫秒,CutList()函數耗時98.01毫秒。
速度比逆向算法提高了一倍,而且應該注意到,CutList()的耗時仍然隨數據量的增大而等比例的增大!!!而從CutList()函數的實現來看,數據量增大,算法耗時應該只增加極少才對。
要知道,只加快一倍速度的CutList(),并不是我所想要的!!!但為什么CutList()函數得不到更高的性能呢???
轉載于:https://www.cnblogs.com/sunday-night/p/6169325.html
總結
- 上一篇: kvm cobbler无人值守批量安装操
- 下一篇: Django框架Day3------之M