Thread들이 자원을 공평하게 나눠가지게 하려면?

bugiii의 이미지

안녕하세요?

GNU Pth를 이용해서 서버를 작성하고 있습니다. (pthread에서는 어떤 동작 행태를 보이는지도 궁금합니다.)

현재 작업하고 있는 부분은 db 커넥션을 pool로 만드는 것입니다. pool에서 커넥션을 얻어 올때, 다음과 같이 간단하게 mutex와 cond를 이용해서 최대 개수면 대기하도록 하였습니다.

public:
        T get()
        {
                ptk::auto_lock lock( mutex_ );

                while( max_ <= used_ )
                      cond_.wait( mutex_ );

                T r( free_.front() );
                free_.pop();
                ++used_;

                return( r );
        }

        void release( const T& t )
        {
                ptk::auto_lock lock( mutex_ );

                free_.push( t );
                --used_;

                cond_.signal();
        }
private:
        std::queue< T > free_;
        ptk::mutex mutex_;
        ptk::cond cond_;
        std::size_t max_;
        std::size_t used_;

문제는 그 커넥션을 사용한 다음 반환했을 때, cond_.signal()이 어떤 쓰레드를 깨울지 정해져 있지 않다는 것입니다.

테스트로 1,000개의 접속을 만들고 빈틈없이 db 쿼리를 날리고 있습니다. 그런데, 쓰레드들이 커넥션을 공평하게 가져가지 못하고, 못가져 오는 것은 아주 오래 시간이 걸리곤 합니다.

오래 기다린 쓰레드를 먼저 깨우도록 할 수는 없는 것인지요? 내부적으로 오래 기다린 쓰레드는 우선 순위를 계속 올려주지 않나요? 대기중인 쓰레드는 우선 순위를 올려주지 않는지요? 오래된 순으로 깨워주는 다른 동기화 방법을 찾아야 합니까?

결국, 작업 대기열을 따로 만들고 이 작업을 따로 만든 작업 쓰레드들이 가져가서 동작하는 방법으로 해결하였지만, 많은 동기화 객체가 사용되기 때문에 조금 안타깝습니다. (기존 쓰레드를 대기열로 만들어서 사용하는 방법도 고려하고 있습니다.)

쓰레드 프로그래밍에서 어떤 자원을 pool로 사용할 때, 쓰레드들이 자원을 공평하게 사용하도록 하는 손쉽고 효과적인 방법은 없을까요?

아 참, pthread에서도 같은 결과를 보일까요?

alsong의 이미지

기본 스케쥴링은 순서를 보장해주지 않습니다.
SCHED_RR은 사용해 봤는데 나머지는 잘모르겠군요. 참고 하시길.

man pthread_attr_setschedparam

Quote:
schedpolicy
Select the scheduling policy for the thread: one of SCHED_OTHER (regular, non-realtime scheduling),
SCHED_RR (realtime, round-robin) or SCHED_FIFO (realtime, first-in first-out). See sched_setpolicy(2) for
more information on scheduling policies.

Default value: SCHED_OTHER.

The realtime scheduling policies SCHED_RR and SCHED_FIFO are available only to processes with superuser
privileges.

The scheduling policy of a thread can be changed after creation with pthread_setschedparam(3).

그나저나 백수 언제 탈출하냐... ㅡㅡ; 배고파라.

pynoos의 이미지

Thread scheduling을 오래기다린 것에 우선순위를 먼저준다든지 하는 스케쥴링에 관한 것은 일반적으로 사용자가 구현하기 힘듭니다.

pthread의 의무 구현사항도 아니고, 스케쥴링이 통일되어 있지도 않습니다.

pth 를 쓰신다니.. pth는 대표적인 user level thread 입니다. 시간날때 그 프로그램의 schedule 관련 c file을 열어서 찬찬히 보세요.. 재밌는 것 많습니다. :)

bugiii의 이미지

Quote:

그 프로그램의 schedule 관련 c file을 열어서 찬찬히 보세요.. 재밌는 것 많습니다

pth스케쥴러가 사용하는 select를 프비의 kqueue로 바꾸고 있습니다.... 재밌지는 않군요... :D

sjang의 이미지

BSD의 kqueue와 리눅스 커널 2.6.x 에 있는 epoll를 비교한
자료가 있습니다. select와는 비교대상이 아닌 듯 합니다.

http://bulk.fefe.de/scalability/

The Future !!!

bugiii의 이미지

본 질문과 상관없이 pth의 select를 이용한 비효율적인 스케쥴러를 프비의 kqueue로 바꾸고 있는 중입니다...

현재까지의 구현 상황은 소켓 접속 1000 개를 1초 간격으로 16바이트씩 보내고 받을 때의 결과입니다. 원래의 select를 이용하면 1000개에서 거의 Idle 타임이 0%가 됩니다.

서버 P4 2.6 1G 프비 4.9: CPU 4.5%, Idle 94.5%
클라이언트 P3 800 512M 프비 4.9: CPU 13.23%, Idle 83.3%

당연히 select하고 kqeue하고는 상대가 안되죠. select는 쓸때없는 검색과 초기화에 너무 시간을 많이 잡아 먹습니다.

bugiii의 이미지

접속 3975개일 경우 테스트입니다.

서버: CPU 18% Idle73.9%
클라이언트: 47.5% Idle 49.2%

현재 상황은 pth 내부의 wait 큐에 fd 관련 이벤트와 타임아웃 이벤트를 kqueue로 처리하도록 해서 매번 WQ를 검색하는 것을 대폭 줄여서 이벤트가 일어날 경우에만 처리하도록 한 상태입니다.

문제는 cancel요청을 처리하는 것인데, 이것도 pipe를 kqueue에 넣어서 해결해 보려고 합니다...

해보고 쓸만하다 싶으면 kldp 오픈 소스로 한번 해보고 싶은데... 워낙 관심이 적은 라이브러리라... 같이 해보실 분은 안 계실까요? 리눅스라면 epoll로 해도 아주 좋을텐데요...

chunsj의 이미지

How about improving StateThreads project with epoll (or kqueue, if
you are BSD freak :-). Refer http://state-threads.sourceforge.net

bugiii wrote:
접속 3975개일 경우 테스트입니다.

서버: CPU 18% Idle73.9%
클라이언트: 47.5% Idle 49.2%

현재 상황은 pth 내부의 wait 큐에 fd 관련 이벤트와 타임아웃 이벤트를 kqueue로 처리하도록 해서 매번 WQ를 검색하는 것을 대폭 줄여서 이벤트가 일어날 경우에만 처리하도록 한 상태입니다.

문제는 cancel요청을 처리하는 것인데, 이것도 pipe를 kqueue에 넣어서 해결해 보려고 합니다...

해보고 쓸만하다 싶으면 kldp 오픈 소스로 한번 해보고 싶은데... 워낙 관심이 적은 라이브러리라... 같이 해보실 분은 안 계실까요? 리눅스라면 epoll로 해도 아주 좋을텐데요...

bugiii의 이미지

네, st도 고려를 해보았고 실험도 해보았습니다.

간단한 서버는 무리없이 사용할 수 있었습니다. 하지만 실제로 DB를 사용하기 시작할 때부터 고민이 되었는데, 예를 들어, MySQL C API는 내부적으로 일반적인 시스템 호출을 이용해서 구현되어 있습니다. 이런 경우 그 시스템 콜들이 st전체를 블럭시키기 때문에 제대로 사용할 수 없었습니다. db 쿼리때 다른 쓰레드들 전부가 멈춰야 한다는 것은...

GNU Pth의 경우에는 시스템 콜을 가로채서 자체적인 pth_*함수로 대체하거나 그에 상응하는 조치를 취해줍니다. (hard call) st에도 그렇게 구현하면 되겠지만 시간도 그렇고...

또하나 걸림돌이 pthread를 대체할 수 있느냐인데 이것도 위의 경우에 문제가 되었습니다. pth는 pthread를 잘 대체해줍니다만 st에는 전혀 고려사항이 아닙니다.

결국 pth를 선택해서 개선하는 것으로 방향을 잡았습니다.

관심 가져주셔서 고맙습니다.

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.