Delphi slow readln()在使用TIdTCPClient设置memcashed值之后
我已经创建了一个类TmemcacheClass,在那里我可以设置并从memcached获取值 它在Delphi Webbroker应用程序中使用,每个线程打开TmemcacheClass并在其生命周期中使用它。这意味着每个线程都会打开TIdTCPClient,并将其连接起来,然后对每个请求进行重用 获取值的速度非常快,如0到1毫秒 设置值的速度也像1毫秒,但在设置后等待readln需要47毫秒 你知道怎么加快速度吗 正在等待的过程store()非常慢Delphi slow readln()在使用TIdTCPClient设置memcashed值之后,delphi,memcached,Delphi,Memcached,我已经创建了一个类TmemcacheClass,在那里我可以设置并从memcached获取值 它在Delphi Webbroker应用程序中使用,每个线程打开TmemcacheClass并在其生命周期中使用它。这意味着每个线程都会打开TIdTCPClient,并将其连接起来,然后对每个请求进行重用 获取值的速度非常快,如0到1毫秒 设置值的速度也像1毫秒,但在设置后等待readln需要47毫秒 你知道怎么加快速度吗 正在等待的过程store()非常慢 行:=tcp.Socket.ReadLn()
行:=tcp.Socket.ReadLn() 添加洞单位,也许我可以在保存后删除readln以加快速度? 如果我删除readln,我想我需要清除套接字,因为我正在重用同一个套接字
unit unitMemcache;
interface
uses
system.sysutils,system.classes,system.JSON,idtcpclient,idGlobal;
type
TmemcacheClass = Class ( Tobject )
private
tcp : TIdTCPClient;
ConnectTimeout : integer;
Fconnected: Boolean;
Ferror: String;
Fcontent: String;
Flinecounter : Integer;
procedure Setconnected(const Value: Boolean);
procedure Seterror(const Value: String);
procedure reportError(e:string);
procedure Setcontent(const Value: String);
public
constructor create( ip : string ) ;
destructor Destroy ( ) ; override ;
procedure store(Key, Value: string);
function Lookup(Key: string ): String;
procedure flush_all;
procedure Delete(Key: string );
procedure connect;
property connected : Boolean read Fconnected write Setconnected;
property error : String read Ferror write Seterror;
property content : String read Fcontent write Setcontent;
End;
implementation
uses system.dateutils;
{ TmemcacheClass }
procedure TmemcacheClass.connect;
begin
try
if not tcp.Connected then
begin
tcp.Connect;
Fconnected:=true;
end;
except
on e: Exception do
begin
reportError(e.Message);
Fconnected:=false;
end;
end;
end;
constructor TmemcacheClass.create(ip: string );
begin
// FConnectTimeout := 4000;
Fconnected:=false;
tcp := TIdTCPClient.Create;
tcp.ConnectTimeout := 1000; // maybe to long , specially if there is a issue...
tcp.ReadTimeout := 2000;
tcp.Host := ip;
tcp.Port := 11211;
tcp.ReuseSocket := rsTrue;
end;
procedure TmemcacheClass.Delete(Key: string);
var
command : String;
stop : Boolean;
line : String;
begin
connect; // just in case
if Fconnected then
begin
command :='delete '+key;
tcp.Socket.Writeln(command);
stop:=false;
repeat
line:= tcp.Socket.ReadLn();
if Line = 'END' then Stop:=true;
if Line = 'DELETED' then Stop:=true;
if Line = 'NOT_FOUND' then Stop:=true;
if (Line = '') and ( not tcp.Socket.ReadLnTimedOut) then Stop:=true;
until Stop;
end;
end;
destructor TmemcacheClass.Destroy;
begin
tcp.Free;
inherited;
end;
procedure TmemcacheClass.flush_all;
var
command : String;
stop : Boolean;
line : String;
begin
Ferror := '';
connect; // just in case
if Fconnected then
begin
command :='flush_all';
try
tcp.Socket.Writeln(command);
except
on e: Exception do
begin
reportError(e.Message);
exit;
end;
end;
stop:=false;
repeat
try
line:= tcp.Socket.ReadLn();
except
on e: Exception do
begin
reportError(e.Message);
exit;
end;
end;
if Line = 'OK' then Stop:=true;
if Line = 'END' then Stop:=true;
if Line = 'STORED' then Stop:=true;
if (Line = '') and ( not tcp.Socket.ReadLnTimedOut) then Stop:=true;
until Stop;
if line <> 'STORED' then line:= tcp.Socket.ReadLn();
end;
end;
function TmemcacheClass.Lookup(Key : string): String;
var
Top : Boolean;
TopString : String;
line : String;
Data : String;
Stop : Boolean;
max_loops : Integer;
topStringValues : Tstringlist;
command : String;
size : Integer;
begin
Ferror := '';
connect; // just in case
result:='';
if Fconnected then
begin
command :='get '+key;
try
tcp.Socket.Writeln(command);
except
on e: Exception do
begin
reportError(e.Message);
exit;
result:='';
end;
end;
Top:=true;
stop := False;
data :='';
max_loops:=0;
size :=0;
repeat
inc(max_loops);
if top then
begin
tcp.Socket.MaxLineLength:=1700; // default first line :-)
try
TopString:= tcp.Socket.ReadLn();
except
on e: Exception do
begin
reportError(e.Message);
exit;
result:='';
end;
end;
top :=false;
if TopString = 'END' then Stop:=true;
if TopString = 'STORED' then Stop:=true;
if TopString = 'SERVER_ERROR' then
begin
Stop:=true;
reportError('SERVER_ERROR : '+key);
end;
if TopString = 'CLIENT_ERROR' then
begin
Stop:=true;
reportError('CLIENT_ERROR : '+key);
end;
if (TopString = '') and ( not tcp.Socket.ReadLnTimedOut) then Stop:=true;
if stop=false then
begin
// Decode top string
topStringValues := Tstringlist.Create;
try
TopString:= StringReplace(TopString,' ','*',[rfReplaceAll]);
topStringValues.Delimiter:='*';
topStringValues.DelimitedText:=TopString;
if topStringValues.Count=4 then
begin
size:=strtointdef( topStringValues[3],1700);
tcp.Socket.MaxLineLength:=size+10; // meassure length add 10 in case :-) for reading
end
else
begin
// error with header
stop:=true;
result:='';
data :='';
end;
finally
topStringValues.Clear;
topStringValues.Free;
end
end;
end
else
begin
try
Line := tcp.Socket.ReadLn(); // Can be to long need to check with a stream...
except
on e: Exception do
begin
reportError(e.Message);
exit;
result:='';
end;
end;
if Line = 'END' then Stop:=true;
if Line = 'STORED' then Stop:=true;
if (Line = '') and ( not tcp.Socket.ReadLnTimedOut) then Stop:=true;
if not stop then data := data+line;
end;
if max_loops > 5000 then
begin
stop :=true;
reportError('max_loops > 500 getting : '+key);
exit;
end;
until stop;
result:=data;
end;
end;
procedure TmemcacheClass.reportError(e: string);
begin
Ferror:=e;
tcp.Disconnect;
Fconnected:=false;
Fcontent:='';
end;
procedure TmemcacheClass.Setconnected(const Value: Boolean);
begin
Fconnected := Value;
end;
procedure TmemcacheClass.Setcontent(const Value: String);
begin
Fcontent := Value;
end;
procedure TmemcacheClass.Seterror(const Value: String);
begin
Ferror := Value;
end;
procedure TmemcacheClass.store(Key, Value: string );
var
command : String;
stop : Boolean;
line : String;
start_time : Extended ;
startLabel : String;
begin
start_time:= now;
Ferror := '';
connect; // just in case
if Fconnected then
begin
command :='set '+key+' 0 0 '+length(Value).ToString;
try
tcp.Socket.Writeln(command);
tcp.Socket.Writeln(Value);
except
on e: Exception do
begin
reportError(e.Message);
exit;
end;
end;
stop:=false;
repeat
try
line:= tcp.Socket.ReadLn();
except
on e: Exception do
begin
reportError(e.Message);
exit;
end;
end;
if Line = 'END' then Stop:=true;
if Line = 'STORED' then Stop:=true;
if (Line = '') and ( not tcp.Socket.ReadLnTimedOut) then Stop:=true;
until Stop;
startLabel:=(MilliSecondsBetween(Now, start_time) ).ToString;
startLabel:=startLabel;
if line <> 'STORED' then line:= tcp.Socket.ReadLn();
end;
end;
end.
unitunitmemcache;
接口
使用
sysutils、system.classes、system.JSON、idtcpclient、idGlobal;
类型
TmemcacheClass=Class(Tobject)
私有的
tcp:TIdTCPClient;
ConnectTimeout:整数;
F连接:布尔型;
费罗:弦;
Fcontent:字符串;
Flinecounter:整数;
过程Setconnected(常量值:布尔值);
过程设置错误(常量值:字符串);
过程报告错误(e:字符串);
过程集合内容(常量值:字符串);
公众的
构造函数创建(ip:字符串);
析构函数Destroy();推翻
过程存储(键,值:字符串);
函数查找(键:字符串):字符串;
程序冲洗所有;
过程删除(键:字符串);
程序连接;
连接的属性:布尔读Fconnected写Setconnected;
属性错误:字符串读取错误或写入设置错误;
属性内容:字符串读取Fcontent写入Setcontent;
结束;
实施
使用system.dateutils;
{TmemcacheClass}
程序TmemcacheClass.connect;
开始
尝试
如果不是tcp,则已连接
开始
tcp.Connect;
Fconnected:=真;
结束;
除了
关于e:Exception-do
开始
报告错误(e.Message);
Fconnected:=假;
结束;
结束;
结束;
构造函数TmemcacheClass.create(ip:string);
开始
//FConnectTimeout:=4000;
Fconnected:=假;
tcp:=TIdTCPClient.Create;
tcp.ConnectTimeout:=1000;//也许要等很久,特别是有问题的时候。。。
tcp.ReadTimeout:=2000;
tcp.Host:=ip;
tcp.端口:=11211;
tcp.ReuseSocket:=rsTrue;
结束;
过程TmemcacheClass.Delete(键:string);
变量
命令:字符串;
停止:布尔;
行:字符串;
开始
连接;//以防万一
如果连接,则
开始
命令:='delete'+键;
tcp.Socket.Writeln(命令);
停止:=错误;
重复
行:=tcp.Socket.ReadLn();
如果行='END',则停止:=true;
如果行='DELETED',则停止:=true;
如果行='NOT_FOUND',则停止:=true;
如果(行=“”)和(不是tcp.Socket.ReadLnTimedOut),则停止:=true;
直到停止;
结束;
结束;
析构函数TmemcacheClass.Destroy;
开始
tcp.Free;
继承;
结束;
程序TmemcacheClass.flush\u all;
变量
命令:字符串;
停止:布尔;
行:字符串;
开始
费罗:='';
连接;//以防万一
如果连接,则
开始
命令:='flush_all';
尝试
tcp.Socket.Writeln(命令);
除了
关于e:Exception-do
开始
报告错误(e.Message);
出口
结束;
结束;
停止:=错误;
重复
尝试
行:=tcp.Socket.ReadLn();
除了
关于e:Exception-do
开始
报告错误(e.Message);
出口
结束;
结束;
如果行='OK',则停止:=true;
如果行='END',则停止:=true;
如果行='STORED',则停止:=true;
如果(行=“”)和(不是tcp.Socket.ReadLnTimedOut),则停止:=true;
直到停止;
如果行“存储”,则行:=tcp.Socket.ReadLn();
结束;
结束;
函数TmemcacheClass.Lookup(键:string):string;
变量
顶部:布尔值;
上弦:弦;
行:字符串;
数据:字符串;
停止:布尔;
max_循环:整数;
topstringvalue:Tstringlist;
命令:字符串;
大小:整数;
开始
费罗:='';
连接;//以防万一
结果:='';
如果连接,则
开始
命令:='get'+键;
尝试
tcp.Socket.Writeln(命令);
除了
关于e:Exception-do
开始
报告错误(e.Message);
出口
结果:='';
结束;
结束;
Top:=正确;
停止:=错误;
数据:='';
最大循环数:=0;
大小:=0;
重复
inc(max_循环);
如果是顶的话
开始
tcp.Socket.MaxLineLength:=1700;//默认第一行:-)
尝试
TopString:=tcp.Socket.ReadLn();
除了
关于e:Exception-do
开始
报告错误(e.Message);
出口
结果:='';
结束;
结束;
top:=假;
如果TopString='END',则Stop:=true;
如果TopString='STORED',则Stop:=true;
如果TopString='SERVER\u ERROR',则
开始
停止:=真;
reportError('SERVER_ERROR:'+key);
结束;
如果TopString='CLIENT_ERROR',则
开始
停止:=真;
reportError('客户端错误:'+键);
结束;
如果(TopString='')和(不是tcp.Socket.ReadLnTimedOut),则停止:=true;
如果stop=false,则
开始
//解码顶部字符串
topstringvalue:=Tstringlist.Create;
尝试
上串:=StringReplace(上串,,'*',[rfReplaceAll]);
TopString值。分隔符:='*';
topStringValues.DelimitedText:=TopString;
procedure TmemcacheClass.store(Key, Value: string );
var
command : String;
stop : Boolean;
line : String;
start_time : Extended ;
startLabel : String;
begin
start_time:= now;
Ferror := '';
connect; // just in case
if Fconnected then
begin
command :='set '+key+' 0 0 '+length(Value).ToString+' noreply';
try
tcp.Socket.Writeln(command);
tcp.Socket.Writeln(Value);
except
on e: Exception do
begin
reportError(e.Message);
exit;
end;
end;
// stop:=false;
// repeat
// try
// line:= tcp.Socket.ReadLn();
// except
// on e: Exception do
// begin
// reportError(e.Message);
// exit;
// end;
// end;
//
//
//
// if Line = 'END' then Stop:=true;
// if Line = 'STORED' then Stop:=true;
// if (Line = '') and ( not tcp.Socket.ReadLnTimedOut) then Stop:=true;
// until Stop;
// startLabel:=(MilliSecondsBetween(Now, start_time) ).ToString;
// startLabel:=startLabel;
//
// if line <> 'STORED' then line:= tcp.Socket.ReadLn();
end;
end;