안녕하세요?
지난번 UDP서버에 5000명 정도의 동시접속이 있을때, 수신되는 데이타처리에 대한 질문을 했었구요, 님이 답변을 주시기 전까지는 답답한 심정이었었는데, 명확하게 방향을 잡는 답변을 주셔서 많이 감사했습니다.
말씀하신대로 TList를 이용해서 수신처리를 해 보았지만 제가 할 수 있는 방법은 new, dispose의 사용, 검색도 순차검색으로 밖에 처리가 안되었습니다. 저의 한계인가봅니다. 이것으로도 되긴 하겠지만 속도가 문제가 되더군요. 그래서 님께서 말씀하신 new를 사용하지 않고 메모리풀을 이용하는 방법과 그리고 검색하는데 있어서도 순차검색이 아닌 트리구조를 이용해 검색을 하려면 아래코드를 어떻게 변경을 해야할지 방향만이라도 간략하게 말씀해 주시면 감사하겠습니다.
잠깐 밑의 코드(UDP서버의 Read이벤트)의 상황을 말씀드리면,
클라이언트에서 보내는 데이타는 ID(이메일 ID와 동일)이구요, 20초에 1번씩 서버로 보냅니다.
이렇게 동시에 전송하는 클라이언트 수는 5000명 정도 되구요.
TList에 저장되는 데이타는 고객ID와 수신시점의 날짜및시간 입니다.
즉, 수신되는 ID가 TList에 없다면 ID와 현시점의 날짜와시간을 TList에 추가하고 있구요,
만약 TList에 ID가 존재한다면 날짜와시간만 현재일시로 업데이트를 해주고 있습니다.
그리고 DB로의 저장은 쓰레드를 이용해 5초 간격으로 하려고 하고 있습니다. (DB저장은 아래코드에 포함 안되었습니다.)
type
TRecvData = Record
UserId : String[15]; //고객 ID
RecvTime : String[20]; //수신시점의 날짜와시간
end;
......
var
RecvDataList : TList;
......
procedure TUDPMainForm.UDPServerUDPRead(Sender: TObject; AData: TStream; ABinding: TIdSocketHandle);
var
pRecvData : ^TRecvData; //TRecvData를 가리키는 포인터 선언
DataStringStream: TStringStream;
i,Count:integer;
NameCompare : String;
begin
DataStringStream := TStringStream.Create('');
try
DataStringStream.CopyFrom(AData, AData.Size);
NameCompare := DataStringStream.DataString; //수신 데이타
i := 0;
Count := 0;
// 이미 수신된 ID가 있는지 검색
for i := 0 to RecvDataList.Count - 1 do
begin
if NameCompare = TRecvData(RecvDataList.Items[i]^).UserId then //이미 수신된 ID가 존재한다면
begin
// 현재날짜 및 시간으로 업데이트
TRecvData(RecvDataList.Items[i]^).RecvTime:=FormatDateTime('YYYY-MM-DD hh:nn:ss', Now);
Count := 1;
Break;
end
else
begin
Count := 0;
end;
end;
// ID가 없다면 TList에 추가
if Count=0 then begin
New(pRecvData);
pRecvData^.UserId:=DataStringStream.DataString;
pRecvData^.RecvTime:=FormatDateTime('YYYY-MM-DD hh:nn:ss', Now);
RecvDataList.Add(pRecvData); // TList에 추가
end;
finally
DataStringStream.Free;
end;
End;
이것은 그냥 Double(또는 TDateTime)로 정의하여 주세요
장점은 메모리활용이 더 좋고 매번 FormatDateTime을 콜해서 String을 변환하는
Overload가 없다는 것 입니다.
둘째는 Function내 Local 변수는 최대로 줄이세요
방법은 세번째를 설명하면서 자연적으로 적용 됩니다.
세쩨는 ShortString의 특성을 이해하고 이것을 한껏 이용하세요
ShortString은 첫번째바이트는 스트링의 길이정보가 있으며 나머지는 스트링입니다.
자 그럼 이와같이 변경되겠죠
type
TRecvData = Record
UserId : String[15]; //고객 ID
RecvTime : double; //수신시점의 날짜와시간
end;
var
RecvDataList : TList;
procedure TUDPMainForm.UDPServerUDPRead(Sender: TObject; AData: TStream; ABinding: TIdSocketHandle);
var
pRecvData : ^TRecvData; //TRecvData를 가리키는 포인터 선언
i : integer;
begin
new(pRecvData);
byte(pRecvData^.UserID[0]) := AData.Size;
AData.read(pRecvData^.UserID[1], AData.Size);
for i := 0 to RecvDataList.Count - 1 do
if pRecvData^.userId = TRecvData(RecvDataList.Items[i]^).UserId then
begin
dispose(pRecvData);
TRecvData(RecvDataList.Items[i]^).RecvTime := now;
exit;
end;
RecvDataList.Add(pRecvData);
End;
트리구조와 메모리풀은 나중에요