Delphi slow readln()在使用TIdTCPClient设置memcashed值之后

Delphi slow readln()在使用TIdTCPClient设置memcashed值之后,delphi,memcached,Delphi,Memcached,我已经创建了一个类TmemcacheClass,在那里我可以设置并从memcached获取值 它在Delphi Webbroker应用程序中使用,每个线程打开TmemcacheClass并在其生命周期中使用它。这意味着每个线程都会打开TIdTCPClient,并将其连接起来,然后对每个请求进行重用 获取值的速度非常快,如0到1毫秒 设置值的速度也像1毫秒,但在设置后等待readln需要47毫秒 你知道怎么加快速度吗 正在等待的过程store()非常慢 行:=tcp.Socket.ReadLn()

我已经创建了一个类TmemcacheClass,在那里我可以设置并从memcached获取值

它在Delphi Webbroker应用程序中使用,每个线程打开TmemcacheClass并在其生命周期中使用它。这意味着每个线程都会打开TIdTCPClient,并将其连接起来,然后对每个请求进行重用

获取值的速度非常快,如0到1毫秒 设置值的速度也像1毫秒,但在设置后等待readln需要47毫秒

你知道怎么加快速度吗

正在等待的过程store()非常慢
行:=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;