日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Tlist删除技巧

發(fā)布時(shí)間:2024/8/26 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Tlist删除技巧 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

二、????從TList開始分析……

為了寫一個(gè)更好的性能ISAPI Filter,我需要更快速地從TList中刪除部分連續(xù)的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; //最后一個(gè)結(jié)點(diǎn) ? for i:= maxI downto 10 do t1.delete(i); ? //正向刪除 ? //for i:=10 to t2.count-10-1 do t2.delete(10); end;

這段代碼是初始化一個(gè)100000個(gè)結(jié)點(diǎn)的List,然后刪除其中的第10個(gè)到倒數(shù)第10個(gè)。這段代碼是逆向的,這樣的刪除速度比較快。如果換成正向刪除(已經(jīng)注釋掉),則速度就慢得非常多了。

這樣的刪除是正常的算法。用測效率的程序測試:逆向刪除算法的耗時(shí)是21.66個(gè)毫秒,則正向刪除的耗時(shí)卻能達(dá)到58099.02個(gè)毫秒。速度慢了2680倍!!!

但這樣就很快了么?不是!我認(rèn)為就算是逆向刪除的速度也并不是快的。

分析TList這個(gè)類的源碼,我們可以看到,它是這樣寫的(我加入了注釋):

procedure TList.Delete(Index: Integer); var ? Temp: Pointer; begin if (Index < 0) or (Index >= FCount) then //判定Index值是否超界 Error(@SListIndexError, Index); ? Temp := Items[Index];?????????????????????? ?//取待刪除結(jié)點(diǎn) ? Dec(FCount); ??????????????????????????????????//Count減一 if Index < FCount then?????????????????????? //將待刪除結(jié)點(diǎn)后的Buffer提前 System.Move(FList^[Index + 1], FList^[Index],(FCount - Index) * SizeOf(Pointer)); if Temp <> nil then?????????????????????????? //發(fā)通告 Notify(Temp, lnDeleted); end;

由于在TList類是將全部的結(jié)點(diǎn)指針存放在FList這個(gè)動(dòng)態(tài)數(shù)組的指針中,所以只需要將Index+1之后的內(nèi)存塊向前移4個(gè)字節(jié),即SizeOf(Pointer),即可實(shí)現(xiàn)Index結(jié)點(diǎn)的刪除。

但是,如果使用這樣來刪除成批連續(xù)的(N個(gè))結(jié)點(diǎn),則要實(shí)現(xiàn)N次system.move()操作,操作的內(nèi)存塊的大小決定了system.move()操作的耗時(shí),而Index值越小的的結(jié)點(diǎn)在FList中越靠前,則system.move()要操作的內(nèi)存塊也就越大。這就是我認(rèn)為上述成批刪除效率不高的原因,也是正向刪除比逆向刪除的耗時(shí)慢了慢了2680倍的原因。

對(duì)于成批刪除,理想的算法是從index+len結(jié)點(diǎn)開始位置,向前移動(dòng)count-index-len個(gè)結(jié)點(diǎn),這樣,就能夠一次完成全部的結(jié)點(diǎn)移動(dòng),實(shí)現(xiàn)刪除操作。這個(gè)思路非常好,至少我認(rèn)為是這樣。為此,我實(shí)現(xiàn)了下面的代碼:

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這個(gè)Buffer中,將刪除后的剩余結(jié)點(diǎn)直接移動(dòng)到Left這個(gè)位置上,從而完成全部的移動(dòng)操作。

然后,我們?cè)僭O(shè)count := count-len;來使用個(gè)數(shù)減少,從而完成了成批量的刪除。

好的,如果一切正常,算法的速度將大幅度提升!OHHH,美妙的想法!

但是,真的是這樣么?我再用效率測試程序來測試了一輪,結(jié)果是這樣的:

1.????測試數(shù)據(jù)為10萬個(gè)結(jié)點(diǎn),則逆向刪除算法耗時(shí)為20.56毫秒,CutList()函數(shù)耗時(shí)9.69毫秒;

2.????測試數(shù)據(jù)為100萬個(gè)結(jié)點(diǎn),則逆向刪除算法耗時(shí)為209.13毫秒,CutList()函數(shù)耗時(shí)98.01毫秒。

速度比逆向算法提高了一倍,而且應(yīng)該注意到,CutList()的耗時(shí)仍然隨數(shù)據(jù)量的增大而等比例的增大!!!而從CutList()函數(shù)的實(shí)現(xiàn)來看,數(shù)據(jù)量增大,算法耗時(shí)應(yīng)該只增加極少才對(duì)。

要知道,只加快一倍速度的CutList(),并不是我所想要的!!!但為什么CutList()函數(shù)得不到更高的性能呢???

轉(zhuǎn)載于:https://www.cnblogs.com/sunday-night/p/6169325.html

總結(jié)

以上是生活随笔為你收集整理的Tlist删除技巧的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。