[HalfNetwork] 작은 데이터 많이 보내기에 문제점이 있는거 같아요..^^

112 views
Skip to first unread message

jini

unread,
Apr 26, 2010, 12:54:16 PM4/26/10
to HalfNetwork
제가 하프네트워크를 사용하여 간단 프로젝트를 진행해 봤는데요

300바이트 정도 되는 데이터를 SendRequest로 300개를 보내니 90000바이트가 서버로 제대로 들어 가는거 같은데

50바이트 정도 되는 데이터를 SendRequest로 300개를 보내니 6400바이트 이하로 서버에 도착하더군요^^;;

15000바이트가 되어야 정상인데 혹시 내부에서 블럭 체인수의 제한이 있어서 64개 이상을 만들지 못하는 것인지 모르겠어
요..^^;;

또 Verifier를 돌려 보는데 TLS(Thread Local Storage) 에서 문제가 생기더군요..^^;;

이건 도저히 모르겠네요..ㅎ^^;;

소스를 살펴볼 참에 올려봅니다..^^;;

--
Subscription settings: http://groups.google.com/group/halfnetwork/subscribe?hl=ko

YoungGi Lim

unread,
Apr 27, 2010, 1:14:01 AM4/27/10
to halfn...@googlegroups.com
for(i=0;i<300;++i)
    SendRequest(50 byte);

이런식으로 보내신 건가요? 저도 한번 테스트 해보도록 하겠습니다.

혹시 Reactor를 사용했을때 발생하는 문제라면

구글 코드 SVN에서 최신 코드를 받아서 다시 테스트해주시면 감사하겠습니다.

이전에 유사한 현상이 있어서 fix를 했는데, download에는 아직 반영이 되어있지 않습니다.

StressTestClient가 그런식으로 구현되어 있으니 그걸로 테스트 해주시는 것도 좋을듯 합니다.

StressTestClient는 아직은 SVN에만 있습니다.

TLS 는 조금 더 자세히 설명해주시면 문제해결에 도움이 될것 같습니다.


2010/4/26 jini <jin...@hanmail.net>

YoungGi Lim

unread,
Apr 27, 2010, 4:19:00 AM4/27/10
to halfn...@googlegroups.com
말씀하신 방법으로 Reactor/Proactor/Windows/Linux 모두 테스트 해보았는데 재현이 되지 않네요.

제가 위에 언급한 그 문제이거나 아니면 PopAllMessage 에서 블럭이 linked list를 이루어서 출력이 되었는데

첫번째 블럭만 처리하시고 나머지를 버려서 발생한일이 아닐가 생각합니다.

PopMessage를 사용하시면 항상 한쌍의 블럭만 출력되서 처리를 간편하게 하실수 있습니다.

하지만 성능에는 PopAllMessage가 좋습니다. StressClient나 TestServer 예제의 PopAllMessage

사용하는 부분을 참고하시면 됩니다.


2010/4/27 YoungGi Lim <javaw...@gmail.com>

jini

unread,
Apr 27, 2010, 8:20:52 AM4/27/10
to HalfNetwork
제 개발환경은 windows7- VS2008 환경에 Proactor를 사용하였습니다.

컴파일은 win32플랫폼에 사용소스는 SVN 최신 소스를 사용하였습니다.

여러가지는 아니지만..^^;; 몇가지를 테스트 해봤는데요..

<TestClient>

void NetworkThread::_OnConnect(unsigned int streamID, const char* ip)
{
//ACE_DEBUG ((LM_DEBUG, "[%t] OnConnect(%d).\n", streamID));
//SendDummyData(streamID);


Sleep(1000);
char sbuffer[50] = {0, };


strcpy(sbuffer,
"abcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcde");

for(int i = 0; i < 300; ++i)
NetworkInstance->SendRequest(streamID, sbuffer, 50);

Sleep(1000);


for(int i = 0; i < 300; ++i)
NetworkInstance->SendRequest(streamID, sbuffer, 50);
}

이런식으로 하고 OnRead 부분은 주석처리 했고요

<TestServer>

void OnRead(unsigned int streamID, char* buffer, unsigned int length)
{
static int recv_outer_size = 0;
recv_outer_size += length;
HALF_LOG(ConsoleLogger, ACE_TEXT("cur_Outer_Recv_Size : %d\n\r"),
recv_outer_size);
}

이런식으로 하고 OnAccept 안은 주석처리 하고 사용해봤습니다.

문제는 PopMessage로 사용하였을때에도 똑같은 현상이 발생하였습니다.

똑같이 Stress Client에서도

<Stress Client>

void SendThread::Update()
{
_ioStatus->Print();

if ((unsigned int)_ioStatus->GetSentBytes() >= _aimSendByte)
{
EventSleep(1000);
return;
}

char buffer[1024] = {0,};
unsigned int sendSize = rand()%50 + 4;
MakeRandomBuffer(buffer, sendSize);
ACE_Message_Block* block;
unsigned int streamId = 0;

for(int i = 0; i < 300; ++i)
{
block = new ACE_Message_Block(sendSize);
block->copy(buffer, sendSize);
if (NetworkInstance->SendRequest(streamId, block, false))
_ioStatus->AddSendBytes(sendSize);
else
printf("SendRequest fail.");
}

EventSleep(30);
}

<TestServer>

void OnRead(unsigned int streamID, char* buffer, unsigned int length)
{
HALF_LOG (ConsoleLogger, ACE_TEXT("OnRead(%d, %d)."), streamID,
length);
ACE_Message_Block* block = NetworkInstance->AllocateBlock(length);
block->copy(buffer, length);
NetworkInstance->SendRequest(streamID, block);
}

를 했을때 되돌려받는 패킷에서 차이가 났습니다.^^

원인은 아직 찾지는 못했습니다.^^;;;

하지만 Sleep을 1이라도 걸어주면 정상적으로 돌아갑니다.

YoungGi Lim

unread,
Apr 27, 2010, 12:28:52 PM4/27/10
to halfn...@googlegroups.com
아 드디어 재현되었습니다. :)

ACE Proactor에서 전송함수가 2가지 있습니다.

ACE_WIN32_Asynch_Write_Stream::write()
하나의 블럭을 전송하는 함수이고

ACE_WIN32_Asynch_Write_Stream::writev()
연결된 블럭들을 한번에 전송하는 함수인데,
연결된 블럭의 갯수가 ACE_IOV_MAX를 넘으면 안되는군요.
ACE_IOV_MAX는 config-win32-common.h에 64로 정의 되어있습니다.

전송해야할 블럭이 쌓이면 성능상 이득이 있는 writev 함수를 사용했는데, 저런 제한이 있었군요.

버그 리포팅해주셔서 감사드리고 소스는 수정해서 1~2일 안에 올리도록 하겠습니다.


2010/4/27 jini <jin...@hanmail.net>

YoungGi Lim

unread,
Apr 28, 2010, 4:28:22 AM4/28/10
to halfn...@googlegroups.com
소스 수정해서 올렸습니다.(구글코드 SVN) 테스트 부탁 드립니다.

전송 요청이 마구 쌓일 경우에 대한 처리가 문제였는데

너무 많은 전송 요청이 올 경우에는 SendRequest에서 false를 리턴하게 될겁니다.

false를 리턴하지 말고 그냥 막쌓아주는 것을 선호하신다면

ServiceImpl.cpp 에
size_t QueueHighWaterMark = 1024*32;

이 부분 값을 변경하시면 이 이상으로도 쌓아줍니다.

다만 메모리 사용량이 꽤 증가할겁니다.

2010/4/27 YoungGi Lim <javaw...@gmail.com>

최흥배

unread,
Apr 28, 2010, 4:50:37 AM4/28/10
to halfn...@googlegroups.com
영기님
size_t QueueHighWaterMark = 1024*32;
이 부분을 하드코딩이 아닌 1024*32 이 값을 서버 설정파일로 초기 실행 시에 설정할 수는 없나요?


2010년 4월 28일 오후 5:28, YoungGi Lim <javaw...@gmail.com>님의 말:



--
MS MVP( VC++ )
Twitter : @jacking75
Blog : http://jacking.tistory.com/

YoungGi Lim

unread,
Apr 28, 2010, 4:57:00 AM4/28/10
to halfn...@googlegroups.com
그렇게 할수는 있는데,

그 값의 의미를 사람들이 쉽게 이해할지는 미지수라고 봅니다.

해당 값은 약간 특별한 상황에서만 의미를 가진다고 보기때문에

일단 변수로 정의해 놓은 수준으로 처리했습니다.

2010/4/28 최흥배 <jack...@gmail.com>
Reply all
Reply to author
Forward
0 new messages