二、    从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删除技巧的更多相关文章

  1. PDF中的空白页面怎么删除,PDF页面删除技巧

    在Word中想要删除其中一页文档的怎么办?直接打开就可以删除了,那么我们如何删除PDF其中几页呢?下面小编就来告诉大家PDF删除页面跟空白页面的方法.想要删除PDF文档中的页面,可以使用PDF编辑器, ...

  2. vim中选择匹配文本删除技巧

    试举几例如下: 如何只保留匹配内容行而删除其他行? :v/pattern/d :help :v 如何对每行只保留匹配内容而删除这一行中的其它内容 :%s/^.pattern.$/\1/g 删除包含特定 ...

  3. linux中WDCP的日志彻底删除技巧

    apache或nginx都有开关默认日志,一个是正常访问日志,一个是错误的日志,目录在 /www/wdlinux/nginx-1.0.15/logs /www/wdlinux/httpd-2.2.22 ...

  4. u盘使用记录、痕迹删除技巧方法

    在日常生活的使用U盘过程当中,系统会记录下大量U盘的使用记录信息,那么接下来小编就来同大家分享介绍如何删除掉这些使用记录的方法知识. 1. 往系统里面添加环境变量devmgr_shownonprese ...

  5. [Unity3D]场景间切换与数据传递(以及物体删除技巧)

    http://blog.163.com/kingmax_res/blog/static/77282442201031712216508/ 先介绍一些基本函数(具体用法自己查文档):---------- ...

  6. 数独高阶技巧之八——SDC

    在本系列的第四篇“简单异数链”中,向大家介绍了XY-Wing等一系列Wing类技巧,并提到可以用(拐弯的)数组的观念来理解这些结构,经过第六篇ALS的学习之后,大家回过头再去看Wing,应该可以发现相 ...

  7. ubuntu基础知识与技巧

    root用户与超级用户的切换 (1)  sudo -i (2)  sudo su (3)  su root 安装升级 查看软件xxx安装内容 dpkg -L xxx 查找软件库中的软件 apt-cac ...

  8. 红黑树LLRB

    LLRB——红黑树的现代实现 一.本文内容 以一种简明易懂的方式介绍红黑树背后的逻辑实现2-3-4树,以及红黑树的插入.删除操作,重点在2-3-4树与红黑树的对应关系上,并理清红黑树相关操作的来龙去脉 ...

  9. Ubuntu 命令手册

    提示:命令太多,查找的时候请用Shift+F. 目录 • 1. 前言 • 2 安装升级 • 2.1 查看软件 xxx 安装内容 • 2.2 查找软件库中的软件 • 2.3 显示系统安装包的统计信息 • ...

随机推荐

  1. IOS 网络浅析-(十一 三方 AFNetworking3.0简介)

    AFNetworking3.0是目前最新的版本,本来打算介绍一下2.6,但是想想2.6名不久矣,就决定不介绍了,有兴趣的小伙伴可以上网查一查.下面我就开始进入正题了. 目前使用人数最多的第三方网络库, ...

  2. Highchart基础教程-图表的主要组成

    一.Highchar图表的主要组成 1.图表标题(Title):图表包含标题和副表题(subTitle,可选). 2.坐标轴(Axis):包括x轴(xAxis)和y轴(yAxis).多个数据列可以共同 ...

  3. C#初步应用

    首先,此次编程是第一次尝试结对编程,我的结对对象博客园地址:http://www.cnblogs.com/cbb111/ 他的源代码链接:https://coding.net/u/cao1417146 ...

  4. 关于在安装MySQL时报错"本地计算机上的mysql服务启动后停止,某些服务在未由其他服务或程序使用时将自动停止"的解决方法

    首先将你下载的MySQL安装或者解压(对应安装版和解压版),下载地址http://dev.mysql.com/downloads/mysql/ 然后复制你安装目录中的my-default.ini,更改 ...

  5. Ubuntu Server 设置PPTP客户端连接

    安装PPTP客户端 apt-get install pptp-linux 设置连接账号信息 sudo vim /etc/ppp/chap-secrets 其中$login_name是登录名:$pass ...

  6. 【python之路1】python安装与环境变量配置

    直接搜索 Python,进入官网,找到下载,根据个人电脑操作系统下载相应的软件.小编的是windows os .下载python-2.7.9.msi 安装包  双击安装程序,进入安装步骤.在安装过程中 ...

  7. java工具类之Graphics

    利用重写paint()方法绘画出一个坐标轴: package huaxian; import java.awt.Color; import java.awt.FlowLayout; import ja ...

  8. angularJS(4)

    angularJS(4) 一:angulaJs的作用域scope Scope(作用域) 是应用在 HTML (视图) 和 JavaScript (控制器)之间的纽带.scope 是一个 JavaScr ...

  9. canvas贝塞尔曲线 - 1

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAvEAAAIcCAIAAADwgGbqAAAgAElEQVR4nOy9a4wb55nn20kOZhq7o8

  10. 基于C/S架构的3D对战网络游戏C++框架 _05搭建系统开发环境与Boost智能指针、内存池初步了解

    本系列博客主要是以对战游戏为背景介绍3D对战网络游戏常用的开发技术以及C++高级编程技巧,有了这些知识,就可以开发出中小型游戏项目或3D工业仿真项目. 笔者将分为以下三个部分向大家介绍(每日更新): ...