转载自:http://www.ylzx8.cn/windows/delphi/73200.html

  本人在做一个测试,服务器是IOCP的,我假定最大链接数是50000个。

  测试背景:如果每个链接之间的数据需要服务器中转的话,那么我需要一个数据容器储存用户的关键数据和连接。

  我简单的做了一段简单的代码,关键代码段如下:

RTest = record
Key: Integer;
Name: String[20];
end;
PTest = ^RTest;
TListType = (ltList, ltStrList, ltHashList); var
List: TList;
StrList: TStringList;
HashList: THAshStringList; procedure TfmMain.addToList(Target: TListType);
var
Total, I: Integer;
P_test: PTest;
T, E, Cardinal;
begin
Total:= 5000000; {此处是关键,5万的时候几乎没有任何区别,500万的时候,区别就特别大了}
T:= GetTickCount;
case Target of
ltList:
begin
for I:=0 to Total do
begin
New(P_test);
P_test.Key:= List.Count + 1;
P_test.Name:= 'Tommy' + IntToStr(List.Count + 1);
List.Add(P_test);
end;
E:= GetTickCount;
mmoInfo.Lines.Add('添加5W条记录到List中需要' + TntToStr(E) + '-' + IntToStr(T) + '=' + IntToStr(E-T));
mmoInfo.Lines.Add('List.Count := '+IntToStr(List.Count));
mmoInfo.Lines.Add('最后一项:'+PTest(List.Last).Name);
mmoInfo.Lines.Add('');
end;
ltStrList:
begin
for I:=0 to Total do
begin
New(P_test);
P_test.Key:= StrList.Count + 1;
P_Test.Name:= 'Tommy' + IntToStr(StrList.Count+1);
StrList.AddObject(IntToStr(StrList.Count), TObject(Integer(P_test)));
end;
E:= GetTickCount;
mmoInfo.Lines.Add('添加5W条记录到StrList中需要'+IntToStr(E) + ' - ' + IntToStr(T) + ' = ' + IntToStr(E - T));
mmoInfo.Lines.Add('StrList.Count := '+IntToStr(StrList.Count));
mmoInfo.Lines.Add('最后一项:'+ PTest(StrList.Objects[StrList.Count - 1]).Name);
mmoInfo.Lines.Add('');
end;
ltHashList:
begin
for I := 0 to Total do
begin
New(P_test);
P_test.Key:= HashList.Count + 1;
P_test.Name:= 'Tommy' + IntToStr(HashList.Count + 1);
HashList.AddObject(IntToStr(HashList.Count),TObject(Integer(P_test)));
end;
E:= GetTickCount;
mmoInfo.Lines.Add('添加5W条记录到HashList中需要'+IntToStr(E) + ' - ' + IntToStr(T) + ' = ' + IntToStr(E - T));
mmoInfo.Lines.Add('HashList.Count := '+IntToStr(HashList.Count));
mmoInfo.Lines.Add('最后一项:'+ PTest(HashList.Objects[HashList.Count - 1]).Name);
mmoInfo.Lines.Add('');
end;
end;
end; procedure TfmMain.btnFindClick(Sender: TObject);
var
I,X: Integer;
P_Tmp: PTest;
T,E: Cardinal;
begin
T:= GetTickCount;
for I := 100 to 300 do
begin
X:= StrList.IndexOf(IntToStr(I));
if X <> -1 then
begin
P_Tmp :=PTest(StrList.Objects[X]);
end;
end;
E:= GetTickCount;
mmoInfo.Lines.Add('StrList中查找200项耗时:' + IntToStr(E - T));
T:= GetTickCount;
for I := 100 to 300 do
begin
X:= HashList.IndexOf(IntToStr(I));
if X <> -1 then
begin
P_Tmp :=PTest(HashList.Objects[X]);
end;
end;
E:= GetTickCount;
mmoInfo.Lines.Add('HashList中查找200项耗时:'+ IntToStr(E - T));
end; procedure TfmMain.FormCreate(Sender: TObject);
begin
List:= TList.Create;
StrList:= TStringList.Create;
HashList:= THashedStringList.Create;
addToList(ltList);
addToList(ltStrList);
addToList(ltHashList);
end; procedure TfmMain.FormDestroy(Sender: TObject);
begin
List.Free;
StrList.Free;
HashList.Free;
end;

  

  测试的时候发现,如果是50000 条数据,那么,这样简单的测试任何效率都看不出来,基本都是在0--20毫秒以内完成添加、查询。

  当我加大数量时,变成500万条时,测试的输出结果是:

添加500W条记录到List中需要10015562 - 10014859 = 703
List.Count := 5000001
最后一项:Tommy5000001 添加500W条记录到StrList中需要10016703 - 10015562 = 1141
StrList.Count := 5000001
最后一项:Tommy5000001 添加500W条记录到HashList中需要10017859 - 10016703 = 1156
HashList.Count := 5000001
最后一项:Tommy5000001 StrList中查找200项耗时:0
HashList中查找200项耗时:1344
StrList中查找200项耗时:0
HashList中查找200项耗时:328
StrList中查找200项耗时:0
HashList中查找200项耗时:328
StrList中查找200项耗时:15
HashList中查找200项耗时:313
StrList中查找200项耗时:16
HashList中查找200项耗时:312
StrList中查找200项耗时:16
HashList中查找200项耗时:312
StrList中查找200项耗时:0
HashList中查找200项耗时:328
StrList中查找200项耗时:0
HashList中查找200项耗时:313

  

分析

  时间都浪费在new(P_test)、List.add/StrList.Add/HashList.Add(里面实施不停的reallocmem)。

  查找是HASH快(自带的不算),hash算法不算难,自己写一个,不然弄个二分法都快过于TStringList。

  THashedStringList是继承自TStringList的,只是它覆盖了IndexOf、IndexOfName两个查询方法,扩充易用性,追求效率应该用TStringList,TStringList是直接从TObject继承来的数组链表。

  你也可以看看contnrs单元,里面有队列、栈、启发式哈希表。

  另外,delphi的list都有capacity属性,用于一次性指定count数,而不是每次重新申请list的长度。因为add时,list发现其count不够,会自动从新分配内存扩充自身长度,这些都是耗时的过程,特别在大长度的循环中,如果长度是可知的,这里你可以在循环前给list.capacity:=total;

最新文章

  1. Spring(Model)
  2. Freemark基本语法知识(转)
  3. cocos2d-x之加法计算器
  4. Excel学习笔记杂荟
  5. Linux shell 脚本攻略之根据扩展名切分文件名
  6. mac 用 brew
  7. [NOI导刊2011]影像之结构化特征
  8. linux ssh 配置 添加用户 另外一种方法
  9. POJ 1961 Period KMP算法next数组的应用
  10. js快速排序法
  11. ADO.Net两种访问数据库模式
  12. C# Task 源代码(2)
  13. dp之背包总结篇
  14. Oracle 12.2报错ORA-15032、ORA-15410或ORA-15411解决
  15. ggplot
  16. [Artoolkit] Can I Use LGPL code for commercial application
  17. Reg2Bat_By Slore(生成同名bat文件,支持XP WIN7 WIN7X64).vbs
  18. 20、uwp打包失败(All app package manifests in a bundle must declare the same values under the XPath *[local-name()=&#39;Package&#39;]/*[local-name()=&#39;Dependencies&#39;])
  19. 演化理解 Android 异步加载图片(转)
  20. Android Studio 学习之 Android SDK快速更新

热门文章

  1. iBatis.net 类的继承extends和懒加载
  2. 【转】PHP中获取当前系统时间、时间戳
  3. maven如何配置
  4. 记录yii2-imagine几个常用方法
  5. SQL Server群集知识介绍
  6. 前端应当了解的Web缓存知识
  7. NSIS检测.NET Framework并在线下载
  8. LPC1769 CAN的自测试模式
  9. CSS 常用基本功能整理
  10. 前端构建工具的用法—grunt、gulp、browserify、webpack