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()函数得不到更高的性能呢???
Tlist删除技巧的更多相关文章
- PDF中的空白页面怎么删除,PDF页面删除技巧
在Word中想要删除其中一页文档的怎么办?直接打开就可以删除了,那么我们如何删除PDF其中几页呢?下面小编就来告诉大家PDF删除页面跟空白页面的方法.想要删除PDF文档中的页面,可以使用PDF编辑器, ...
- vim中选择匹配文本删除技巧
试举几例如下: 如何只保留匹配内容行而删除其他行? :v/pattern/d :help :v 如何对每行只保留匹配内容而删除这一行中的其它内容 :%s/^.pattern.$/\1/g 删除包含特定 ...
- linux中WDCP的日志彻底删除技巧
apache或nginx都有开关默认日志,一个是正常访问日志,一个是错误的日志,目录在 /www/wdlinux/nginx-1.0.15/logs /www/wdlinux/httpd-2.2.22 ...
- u盘使用记录、痕迹删除技巧方法
在日常生活的使用U盘过程当中,系统会记录下大量U盘的使用记录信息,那么接下来小编就来同大家分享介绍如何删除掉这些使用记录的方法知识. 1. 往系统里面添加环境变量devmgr_shownonprese ...
- [Unity3D]场景间切换与数据传递(以及物体删除技巧)
http://blog.163.com/kingmax_res/blog/static/77282442201031712216508/ 先介绍一些基本函数(具体用法自己查文档):---------- ...
- 数独高阶技巧之八——SDC
在本系列的第四篇“简单异数链”中,向大家介绍了XY-Wing等一系列Wing类技巧,并提到可以用(拐弯的)数组的观念来理解这些结构,经过第六篇ALS的学习之后,大家回过头再去看Wing,应该可以发现相 ...
- ubuntu基础知识与技巧
root用户与超级用户的切换 (1) sudo -i (2) sudo su (3) su root 安装升级 查看软件xxx安装内容 dpkg -L xxx 查找软件库中的软件 apt-cac ...
- 红黑树LLRB
LLRB——红黑树的现代实现 一.本文内容 以一种简明易懂的方式介绍红黑树背后的逻辑实现2-3-4树,以及红黑树的插入.删除操作,重点在2-3-4树与红黑树的对应关系上,并理清红黑树相关操作的来龙去脉 ...
- Ubuntu 命令手册
提示:命令太多,查找的时候请用Shift+F. 目录 • 1. 前言 • 2 安装升级 • 2.1 查看软件 xxx 安装内容 • 2.2 查找软件库中的软件 • 2.3 显示系统安装包的统计信息 • ...
随机推荐
- wpf版扫雷游戏
近来觉得wpf做出来的界面很拉风,自己也很喜欢搞些小游戏,感觉这做出来的会很炫,很装逼,(满足自己的一点小小的虚荣心)于是就去自学,发现感觉很不错,可是属性N多,太多了,而且质料也少,很多不会用,只会 ...
- iOS中多线程的实现方案
什么是主线程? 一个iOS程序运行后,默认会开启一条线程,称为“主线程”或“UI线程” 主线程的主要作用 1.显示/刷新UI界面 2.处理UI事件(比如点击事件,滚动事件,拖拽事件) 主线程的使用注意 ...
- java正则表达式
java正则表达式 1.Java正则表达式的语法与示例: http://baike.xsoftlab.net/view/207.html 2.Java 正则表达式: http://www.runo ...
- 每天5分钟 玩转OpenStack 目录列表
最近在学习 OpenStack 的相关知识,一直苦于 OpenStack 的体系庞大以及复杂程度,学习没有进度,停滞不前.偶然机会在 51CTO 上发现了一个热点的专题关于 OpenStack 的,题 ...
- 最新官方WIN10系统32位,64位系统ghost版下载
系统来自:系统妈 随着Windows 10Build 10074 Insider Preview版发布,有理由相信,Win10离最终RTM阶段已经不远了.看来稍早前传闻的合作伙伴透露微软将在7月底正式 ...
- windows10的第一天使用总结
一.快速开机设置 我的电脑配置如图,装有VS2015 2010 OFFICE等常用开发工具,在线升级后开机速度并没有明显提升. 1.保证windows font cache service服务启动,3 ...
- 【C】.h头文件的重复包含问题
.h头文件存在的意义就是封装,可以方便多个.c源文件使用,但要防止.h头文件被同一个.c源文件多次包含. 例如, io.h文件 #ifndef _IO_H_ #define _IO_H_ #defin ...
- CANopen学习——PDO
查找资料时,发现一个很好的博客,博主剖析的通俗易懂 http://www.cnblogs.com/winshton/p/4897556.html PDO定义: 过程数据对象,用来传输实时数据.因为 ...
- Yahoo14条军规-前端性能优化
1.尽可能减少HTTP请求数 什么是http请求? 2.使用CDN(内容分发网络) 什么是CDN? 3.添加Expire/Cache-Control头 Expire Cache-Control 4.启 ...
- HTML 学习笔记 JavaScript(面向对象)
现在让我们继续跟着大神的脚步前进 学习一下JavaScript中的面向对象的思想,其实作为一个iOS开发者,对面向对象还是比较熟悉的,但是昨晚看了一下Js中的面向对象,妈蛋 一脸萌比啊.还好有大神.让 ...