Delphi 的TStringBuilder防止服务器内存碎片化
Delphi 2009+ 的 System.SysUtils提供了一个类似.Net的StringBuilder,用于存储字符数组。
很多人不明白为什么要用TStringBuilder, Delphi中有string,有几乎所有TStringBuilder的功能函数, System.SysUtils中还有TStringHelper方便扩展String,更方便String的使用。
从Delphi提供的源码看,TStringBuilder与string最大的区别是,TStringBuilder是可以预先申请了内存空间,并限制最大内存空间,不会自动释放,而string是用多少申请多少内存,自动释放。
由此可见TStringBuilder相对于String的优势有2:
1.在开发服务器软件时,使用TStringBuilder池,可以有效地防止内存碎片化.
2.由于不需要开辟新的存储空间存储更大的字符串,预先申请内存的TStringBuilder的运行效率将超越string.
下面的代码中TServerString继承自TStringBuilder,内存空间限制大小为MaxMemorySize,, 当准备写入的字符将要超过内存大小时,将自动抛出异常,
服务器软件可以接获此异常后处理。
下面的代码有待测试:
1 unit Iocp.ServerString; 2 3 interface 4 5 uses SysUtils, Classes; 6 7 type 8 TServerStringPool=class; 9 TServerString=class(TStringBuilder) 10 protected 11 class var FPool:TServerStringPool; 12 constructor Create; 13 public 14 destructor Destroy;override; 15 end; 16 17 TServerStringPool=class 18 protected 19 FList:TThreadList; 20 public 21 constructor Create(Capacity:Integer); 22 destructor Destroy;override; 23 function GetString:TServerString; 24 procedure FreeString(Value:TServerString); 25 end; 26 27 implementation 28 29 const 30 MaxMemorySize=16384; 31 32 33 { TServerString } 34 35 constructor TServerString.Create; 36 var 37 N:Integer; 38 begin 39 N:=(MaxMemorySize-InstanceSize) div SizeOf(Char); 40 inherited Create(N, N); 41 end; 42 43 destructor TServerString.Destroy; 44 begin 45 FPool.FreeString(Self); 46 end; 47 48 { TServerStringPool } 49 50 constructor TServerStringPool.Create(Capacity: Integer); 51 var 52 i: Integer; 53 L:TList; 54 begin 55 inherited Create; 56 L:=FList.LockList; 57 try 58 for i := 1 to Capacity do 59 begin 60 L.Add(TServerString.Create); 61 end; 62 finally 63 FList.UnlockList; 64 end; 65 end; 66 67 destructor TServerStringPool.Destroy; 68 var 69 i: Integer; 70 L:TList; 71 begin 72 L:=FList.LockList; 73 try 74 for i := L.Count-1 to 0 do 75 TStringBuilder(L[i]).Free; 76 finally 77 FList.UnLockList; 78 end; 79 FList.Free; 80 inherited; 81 end; 82 83 procedure TServerStringPool.FreeString(Value: TServerString); 84 begin 85 FList.Add(Value); 86 end; 87 88 function TServerStringPool.GetString: TServerString; 89 var 90 L:TList; 91 begin 92 L:=FList.LockList; 93 try 94 if L.Count=0 then 95 begin 96 Result:=TServerString.Create; 97 end 98 else 99 begin 100 Result:=TServerString(L[L.Count-1]); 101 L.Delete(L.Count-1); 102 end; 103 finally 104 FList.UnlockList; 105 end; 106 end; 107 108 initialization 109 TServerString.FPool:=TServerStringPool.Create(10240); 110 finalization 111 TServerString.FPool.Free; 112 end.