1. 程式人生 > >Delphi容器類之---Tlist,TStringlist,THashedStringlist的效率比較

Delphi容器類之---Tlist,TStringlist,THashedStringlist的效率比較

本人在做一個測試,伺服器是IOCP的,我假定最大連線數是50000個。

如果每個連結之間的資料需要伺服器中轉的話,那麼我需要一個數據容器儲存使用者的關鍵資料和連結。

以上是測試背景。

剛剛我簡單的做了一段簡單的程式碼,關鍵程式碼段如下:
RTest = record
    Key:  Integer;
    Name: String[20];
  end;
PTest = ^RTest ;
TListType = (ltList,ltStrList,ltHashList);

var
  List:     TList;
  StrList:  TStringList;
  HashList: THashedStringList;


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中需要'+IntToStr(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;

相關推薦

Delphi容器---TListTStringList、TObjectList以及一個例程的程式碼分析

  看了這裡標題,大家可能以為我會談TListBox控制元件,那就錯了。我要談的是Delphi提供給我們的具有列表性質的類:TStringList、TList和TObjectList。TStringList用來存放字串,TList存放指標,而TObjectList則存

Delphi容器---TlistTStringlistTHashedStringlist效率比較

本人在做一個測試,伺服器是IOCP的,我假定最大連線數是50000個。如果每個連結之間的資料需要伺服器中轉的話,那麼我需要一個數據容器儲存使用者的關鍵資料和連結。以上是測試背景。剛剛我簡單的做了一段簡單的程式碼,關鍵程式碼段如下:RTest = record    Key:

【轉】誰說Delphi沒有雜湊?--DelphiTStringListTHashedStringList的效能對比

曾經看到很多人在嚷嚷Delphi沒有雜湊表,這些人的動手意識姑且不論,卻還有很多人以此來證明Delphi比別的語言垃圾,實在是... 好,牢騷打住,轉接正題。 TStringList是我們常用的字串列表型別,用法就不在這裡贅述,但是,在資料其項數增多時,其搜尋(主要是na

Delphi 小談TList

最近開發程式需要使用TList功能,轉載此文章,以作參考。 看了這裡標題,大家可能以為我會談TListBox控制元件,那就錯了。我要談的是Delphi提供給我們的具有列表性質的類:TstringList、TList和TObjectList。TstringList用來存放字

C++11中對容器的各種循環遍歷的效率比較

ets normal pre unsigned int qdebug tex contain string 1 #include "CycleTimeTst.h" 2 #include <string> 3 #include <vector&

String 型equals方法和int == 方法效率比較

方法 新建 錯誤 == 總數 進行 差距 拆裝箱 自己 最近寫了一個遞歸方法,在進行比較判斷的時候,因為都是integer類型,而integer類型在大於127或者小於-128時會在新建一個,這是因為integer類型的拆裝箱機制, 之前沒有考慮過equals方法和 =

Python路第二天基礎2-基本數據

cheng python ech odi lun ron zid ast aof %E5%BE%AE%E4%BF%A1%E5%85%AC%E5%85%B1%E5%8F%B7%E7%9A%84PHP%E5%BC%80%E5%8F%91%E5%9F%BA%E7%A1%80%E7

《代碼整潔道》總結——系統測試叠進

邏輯 測試的 總結 容器管理 重復 -s 整潔之道 整潔 容器 類 類和前面說的函數一樣,應該功能單一且小巧,越小耦合性越低 系統 把系統的構造和使用分開。不要讓構造影響使用,也不要讓程序的運行反過來影響構造。這就需要工廠模式來創建一個容器管理類的生成,IOC是一種很

Python基礎知識:hello world註釋變量數據

我們 重要 一個 yield code oba () turn 編程語言   從接觸編程語言以來,在我腦海裏經常有三個問號: 這是什麽? 這個有什麽用? 這個怎麽用?   我覺得初學一個東西,把這三個問號都搞明白,那麽剩下的就是孰能生巧的過程了,在接下來的博客中,每個知

oop思維意識 模塊命名空間擴展繼承 、組合、mixin三種模式

經驗 .cn 第四版 分享圖片 實例 pytho 模塊 組合 為什麽 python的書都是講怎麽創建類怎麽實例化對象,一般會用使用了,但還不具備這種編程意識。這是從python學習手冊第四版節選出來的,書中說oop不僅是一種技術,更是一種經驗。學習大神的看法,為什麽需

PythonMetaclass詳解Python

turned 除了 方法 寫法 找到 類對象 global 所在 code 本人Java程序員一枚,這幾天閑來無事就自學了下Python,學到Metaclass感覺有點迷惑,就在網上查相關資料,在棧溢出(stackoverflow)網站上看到一個關於metaclass的回答

mysql系列2------數據索引存儲引擎

事務 年份 自動 create default timestamp cas 長度 刪除 一、Mysql數據類型: 1、數值類型: 整數類型:使用unsigned修飾時,只取正值,數值不夠指定寬度時,在左邊補空格 整

Expo大作戰(二十七)--expo sdk apiUtil(expo自帶工具)tackSnapshotAsyncSvgSQLite

help count 開發 段落 mda and mpat str 語句 簡要:本系列文章講會對expo進行全面的介紹,本人從2017年6月份接觸expo以來,對expo的研究斷斷續續,一路走來將近10個月,廢話不多說,接下來你看到內容,講全部來與官網 我猜去全部

XML自動生成添加修改刪除的屬性

pes 表示 創建 BE gen name 待完善 ica bsp 1. class ClassHelperDemo { public static void Main() { #re

Qt容器的對象模型及應用(線性結構篇:對於QList來說sharable默認是false的但對於接下來講的QVector來說sharable默認是true)

連續 ble begin 當我 保存 img article net 內容 用Qt做過項目開發的人,肯定使用過諸如QList、QVector、QLinkList這樣的模板容器類,它們雖然名字長的不同,但使用方法都大致相同, 因為其使用方法都大體相同,很多人可能隨便拿一個容器

一個有新增元素(add)和獲取元素數量(size)方法。 啟動兩個線程。線程1向容器中新增數據。線程2監聽容器元素數量容器元素數量為5時線程2輸出信息並終止

override tac trace add syn countdown print import 數據 方式一: /** * 兩個線程要是可見的所以要加上votalile */public class Test_01 { public static void

大資料scala(三) --- 的檢查、轉換、繼承檔案特質trait操作符applyupdateunapply高階函式柯里化控制抽象集合

一、類的檢查和轉換 -------------------------------------------------------- 1.類的檢查 isInstanceOf -- 包括子類 if( p.isInstanceOf[Employee]) {

OC學習篇---的三大特性 封裝繼承多型

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

JS 語法--物件型別(構造器classthis)高階物件(高階Minix模式)

1、JS 物件型別   JavaScript 是一種基於原型(prototype)的面嚮物件語言,而不是基於類的面嚮物件語言   C++, Java 有類Class 和例項Instance 的概念,類是一類事物 的抽象,而例項則是類的實體。   JS是基於原型的語言,它只有原型物件的概念,原型物件就是一

過濾流FilterInputStream實現BufferedInputStream物件流ObjectOutputStream 實現資料持久化

使用過濾流(高階流)BufferedInputStream、BufferedInputStream優化檔案拷貝功能 import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.i