쓰레드에서 네트웍으로 send할 때 스케줄링(?)...
조그만 네트웍 프로그램을 하나 짰습니다.
제딴에 꽤나 어렵사리 구현했는데 막히는 부분이 있어서 질문을 올립니다.
링크드 리스트로 구성된 데이타 구조체가 있습니다.
첫 구조체는 메인 큐로 사용되며 멤버로 가지고 있는 큐에 데이타의 포인터를 저장합니다.
나머지 링크드 리스트의 노드들은 클라이언트가 붙을 때 생성되는 쓰레드가 사용합니다.
이 노드들의 큐에는 메인 큐의 데이타를 그대로 복사해서(포인터만) 가지고 있습니다.
메인 큐에 실시간으로 발생하는 데이타를 저장(물론 포인터만)하고 각 클라이언트용 큐에
포인터를 복사 합니다. 클라이언트 처리를 하는 쓰레드는 각자 알아서 자신의 큐에 있는
데이타를 네트웍으로 날립니다.
reference count란 개념을 써서 충돌은 피했습니다.
원하는 동작은..
메인 큐에 쌓인 데이타가 클라이언트 큐로 복사된(포인터만) 후 각각의 클라이언트가
차례대로 한번씩 send를 하는것입니다. (여러개의 데이타가 큐에 존재하더라도)
그런데 현재...
A, B, C 라는 클라이언트가 붙어 있고 메인 큐에 5개의 데이타가 존재한다면
각각의 클라이언트 큐에 5개의 포인터를 복사하고 각각의 클라이언트가 네트웍으로
send를 하는데 A의 큐에 있는 데이타 5개를 모두 send후에 B의 데이타를 send, C의
데이타를 send.. 그리고 다시 메인큐에서 각각의 클라이언트 큐에 포인터를 복사..
이런식으로 동작을 하고 있습니다.
깡패도 아니고 왜 몰려다니는지...
한두개의 데이타와 한두개의 클라이언트일 경우 별 문제가 없는데..
10개의 데이타가 쌓여있고 클라이언트가 10개만 붙었다고 가정해도 마지막 클라이언트는
90번의 send가 진행후 첫 데이타를 send할 수 있으니 문제가 심각해지네요..
어떤 해결 방법이 있을까요?
차례로 한번씩은 아니여도 최소한 그 근처까지는 가야할거 같은데..
통 방법을 모르겠습니다.
참 조건이 더 있습니다.
메인 큐에는 실시간으로 데이타가 쌓이고 지연은 최소한으로 해야합니다..
제가 생각하기론10의 스레드가 10개의 packet을 보낸다고 했
제가 생각하기론
10의 스레드가 10개의 packet을 보낸다고 했을때
9번째건 90번의 sending이 일어난후에 보내진다고 한게 문제라구 하셨는데요.
10개의 packet을 보낼때만 그렇게 보일꺼고, 만약 100-200개의 데이터씩을 보내게 된다면 좀더 잘분배가 되지 않을까합니다.
즉 한 context switching이 일어나기 전까지의 일들은 한번에 일어날것이고 한 task에서 switching이 일어나기까지도 일이 남아있다면 제대로 잘분배가 될것입니다.
최대한의 지연이 없어야한다면 지금같은방법이 최선이고, 정 한패킷씩 나눠서 보내야한다면 강제로 schedule해주는 방법이 있겠네요.
"만약 100-200개의 데이터씩을 보내게 된다면 좀더 잘분배가 되지 않
"만약 100-200개의 데이터씩을 보내게 된다면 좀더 잘분배가 되지 않을까합니다. "
어떤 이유에서 그런지 조금 더 설명 부탁드립니다.
데이타 크기를 줄여서 대략 20개 정도의 클라이언트를 붙여 봤는데 조금 분배되기는 합니다만 그래도 뭉쳐다니네요..
데이타가 영상이라 지금 처럼 뭉쳐 다니면 클라이언트 측에서 볼 때 툭툭 끊기는 현상이 발생하기 때문에 이런 현상을 최소한으로 억제 해야함 합니다.
스케줄링을 할 방법을 찾고 있는데 별다른 뾰족한 방법이 눈에 안 띄이길래 질문을 올린겁니다.
...
데이터를 처리하고 난 후 usleep 시간을 아주 짧게 주고 호출해줘서
CPU를 강제로 다른 쓰레드에게 양도해보시죠
흠.
저도 비슷한 문제때문에..
현재 큐에 n 개 이상의 데이타가 쌓여 있으면 usleep를 호출하는 방식을 사용한적이 있습니다. usleep은 짧은 시간동안 호출했구요
n 이 처리속도를 좌우하는 요소겠죠
(그래서 변수명을 speedfactor로 했었던 기억이 .. )
그런다음 테스트를 위하여 대량의 데이타를 오랜시간 발생시켜보니깐..
큐에 들어 있는 데이타의 개수가 거의 일정하게 유지되면서
큐에 n개 이상의 데이타가 쌓인 상태에서 다른 스레드가 처리안하고 놀고 있지는 않았구요
이렇게 하여 만약 클라이언트에의 응답속도가 느리면
n의 값을 줄이면 되겠더라구요
결국 클라이언트의 응답속도를 조절하는게 중요합니다.
저도 먼가 다른 좋은 방법이 있으면 알고 싶네요 ㅎㅎ ^^
@.@
각 클라이언트마다 보낸 갯수나 양에 따라 자신만의 실행순위를 결정하는건
각 클라이언트마다 보낸 갯수나 양에 따라 자신만의 실행순위를 결정하는건
어떨까요. 클라이언트 각자가 cpu 사용이나 부하 정도에 따라 절적히 usleep
같은걸 호출하게 하는 겁니다.
잘못하면 usleep에 대한 경쟁관계도 발생할수 있겠네요.
알고리즘 잘 구성해야 겠네요.
---------
간디가 말한 우리를 파괴시키는 7가지 요소
첫째, 노동 없는 부(富)/둘째, 양심 없는 쾌락
셋째, 인격 없는 지! 식/넷째, 윤리 없는 비지니스
이익추구를 위해서라면..
다섯째, 인성(人性)없는 과학
여섯째, 희생 없는 종교/일곱째, 신념 없는 정치
usleep을 호출하는 방식을 쓰고 있었는데 호출시 시점과 sleep 시
usleep을 호출하는 방식을 쓰고 있었는데 호출시 시점과 sleep 시간을 조금 더 조절해보아야 겠네요..
리눅스에서는 이 방법 밖에 없는건가?
찾아보니까 솔라리스에서는 스케줄링에 관한 옵션 있던데..
"현재 큐에 n 개 이상의 데이타가 쌓여 있으면 usleep를 호출하는 방식을 사용한적이 있습니다. usleep은 짧은 시간동안 호출했구요"
괜찮은 방법 같습니다..
당장.. 실험해 봐야지...
스케쥴링시 고려할 사항으로 통신응답시간을 고려해야 합니다.* 전송
스케쥴링시 고려할 사항으로 통신응답시간을 고려해야 합니다.
* 전송 프로토콜이 TCP? UDP?
* TCP라면 A,B,C,D가 각기 다른 latency를 가진다고 봐야 할것이므로, 보다 신중한 고려가 필요합니다.(실험실 말고 실제 망에서는 더욱 심할수도..)
* UDP라면 블록되지 않을 것이므로, 그부분에 대한 문제는 없겠으나, 다른 문제를 고려해야 하겠지요.
그외 실제 상황에 비추어 멀티캐스트, 브로드캐스트를 사용할 수도 있겠지요.
통신 응답시간은 고려 대상에서 제외시켰습니다.정확히 말하면 고려를 하
통신 응답시간은 고려 대상에서 제외시켰습니다.
정확히 말하면 고려를 하지 못 했습니다. --;;
TCP를 썼으며 sleep 시간과 위치 조정으로 어느정도 해결된거 같습니다.
답변주신 모든분께 감사 드립니다.
[quote="namacin"]... sleep 시간과 위치 조정
매우 우려스럽군요. 이 방식으로 동기화 시키면 외부 요인에 의해 프로그램이 돌기도 하고 안돌기도 하는 상태로 갈 가능성이 농후해 보입니다.
댓글 달기