소켓에 대해서는 잘 모르겠습니다만... 그리고 리눅스에 대해선 아리매님의 말씀이 맞는 거 같고요.
리눅스가 아닌 Win32 환경에서 한 프로세스 내의 쓰레드 갯수 제한에 대해서 써보지요.
(오프라인에서 몇번 언급한 적이 있습니다)
다음은 현재 집필중인 책의 '프로젝트 옵션'에 대한 부분 중, 'Max Stack Size' 옵션에 대한 설명입니다.
간단히 말하면, "윈도우에서 프로세스 당 쓰레드 갯수는 (2GB / 최대 스택 사이즈)로 제한된다"는
얘깁니다.
------------------------------------------------
Max Stack Size는 멀티 쓰레드 프로그램에서 최대 생성가능한 쓰레드의 개수와 밀접한 관련이 있다. 결론부터 말하자면, 기본 설정 상태에서 컴파일을 하면 프로그램이 생성할 수 있는 쓰레드의 개수가 2,000개 정도로 제한된다.
C++Builder에서 생성한 애플리케이션을 포함해 보통 윈도우 애플리케이션들은 기본적으로 최대 스택 크기를 1MB로 지정해놓고 있는데(0x00100000을 10진수로 환산하면 1MB이다), 이 최대 스택 크기의 메모리는 항상 사용하고 있는 것은 아니지만 일단 프로그램이 실행된 직후에 메모리 주소공간에서 예약되므로 다른 용도로는 사용할 수 없다.
그리고 멀티 쓰레드 프로그램에서 쓰레드들은 디폴트 쓰레드(프로그램 자체)에서 설정한 스택 설정을 공유하므로, 프로그램에서 최대 스택이 1MB로 지정되어 있으면 각 쓰레드들도 최대 스택 크기가 1MB씩 지정되게 된다. 결국, 모든 쓰레드마다 1MB씩의 주소공간을 점유하게 되는 것이다.
그런데 윈도우의 주소공간은 총 4GB로, 그중 애플리케이션이 메모리 할당으로 사용할 수 있는 공간은 하위 2GB이다. 결과적으로, 기본 설정으로 프로그램을 만들면 단순 계산만으로도 2GB / 1MB = 2,048 개의 쓰레드밖에 만들지 못한다. 여기서 디폴트 쓰레드를 제외하고, 또 프로그램에서 여러 목적으로 할당해 사용하는 메모리를 제외하면 약 2,000개 안팎의 쓰레드밖에 생성하지 못한다.
2,000개의 쓰레드가 충분히 많은 것인지 아닌지는 독자가 만드는 프로그램에 따라 다를 것이다. 일반적으로는 충분하다고 할 수 있겠다. 하지만 경우에 따라 2,000개의 제한은 혹독할 수도 있다.
이런 경우에는 Max stack size의 값을 낮추어야 한다. 예를 들어, 1MB에서 512kB로 줄인다면(16진수로 0x00080000), 최대 쓰레드 개수는 두배로 늘어나서 4,000개까지 생성할 수 있게 된다. 물론 더 많은 쓰레드가 필요하다면 최대 스택 크기를 더 낮추면 될 것이다. 하지만 너무 적은 스택은 프로그램의 실행에 문제를 일으킬 수도 있으므로, 주의해서 설정해야 한다.
------------------------------------------------
아래 아리매님의 말씀에서처럼, 제가 알기로도 리눅스 쓰레드는 내부적으로 프로세스와 유사하게
구현되어 있으므로 윈도우와는 다를 것입니다.
윈도우 쓰레드는 리눅스 쓰레드와는 완전히 다르니까요.
하지만... 여전히 이런 의문이 남는군요.
윈도우 환경에서 위와 같은 한계가 있을 수 밖에 없는 근본적인 원인은 다음과 같습니다.
1. 총 가상메모리 공간이 4GB이고 애플리케이션이 직접 사용하는 영역은 하위 2GB이다.
2. 프로세스와 쓰레드가 같은 메모리 주소공간을 공유하므로 쓰레드의 최대 스택 사이즈가
프로세스의 메모리 공간을 점유하게 된다.
3. 하나의 스택은 메모리에 분산될 수 없으므로 쓰레드가 시작되는 동시에 최대 스택사이즈만큼의
메모리가 예약되게 된다.
1번의 경우에는, 리눅스 환경의 경우에도, 1번과 같은 프로세스의 주소공간에는 한계가 있을 것입니다.
그리고 리눅스라고 하더라도 프로세스의 어드레싱 가능한 주소공간은 4GB로 제한 될 것입니다.
(32비트 OS에서 메모리 어드레싱은 2의 32승, 즉 4GB)
그리고 2번의 경우에도, 쓰레드의 목적상, 논리적으로 프로세스와 주소공간을 공유할 것입니다.
3번 항목의 경우에도, 스택의 기본적인 속성상 윈도우와 리눅스가 다를 수 없을 것입니다.
이와 같이 추리해보면, 리눅스의 경우에도 윈도우와 같은 스택사이즈에 따른 쓰레드 갯수의
한계가 있을 것이라는 생각이 드는군요.
윈도우에서 4GB 중에서 상위 2GB를 DLL 예약공간인 것처럼 리눅스에서도 DSO가 예약하고 있는지
모르겠는데, 만약에 그렇다면 윈도우에서처럼 2GB로 주소공간이 제한된다는 얘기지요.
그런 경우에 아리매님이 인용하신 글에서첢 최대 스택사이즈가 8MB라면, 프로세스당 쓰레드 갯수는
최대 2048/8=250개가 되는 것입니다.
그리고 전체 4GB를 다 사용할 수 있다면 4096/8=500개가 되겠지요.
이와 같은 점을 생각해보면.. 아리매님이 말씀하신 제한(2048개)보다 이 제한이 훨씬 적으므로,
실제로 프로세스당 쓰레드 갯수는 250개 혹은 500개의 한계를 가질 것입니다.
이런 가정에 대해 예외적인 상황을 생각해보면...
1. 리눅스에서는 프로세스와 쓰레드가 주소공간을 공유하지 않는 경우 (설마?)
2. 리눅스가 윈도우와는 달리, 쓰레드의 스택 사이즈가 개별적으로 지정할 수 있는 경우
제가 리눅스 환경에서 테스트할 수 있으면 좋겠는데... 쩝~
누구 이 문제에 대해 더 잘 아시는 분이나, 실제로 테스트해보시는 분이 있으시면 좀 알려주세요~
그럼...
최준호.스페로 님이 쓰신 글 :
: 안녕하세요 스페로입니다...
:
: 요즘 학과 교수님과 연구중인 프로젝트를 하다가... 떠오른 질문인데...
:
: 이곳 자게가 여러 경험많은 개발자들의 경험을 이야기 할수 잇는 좋은 공간 같아..
:
: 다음과 같은 질문을 쌔웁니다....
:
: 1. 머신당 프로세스 생성 에 한계 갯수?
:
: process / machine (한 컴퓨터가 생성할수있는 프로세스수)
:
: 2. 프로세스가 생성할수 있는 자식프로세스의 한계 갯수?
:
: child process / process (한프로세스가 거느릴수 잇는 자식프로세스)
:
: 3. 프로세스가 생성할수 있는 스레드의 수
:
: thread / process
:
: 4. 한시스템이 생성할수 있는 socket의수
:
: socket / machine
:
: 5. 한프로세스가 생성할수 있는 socket의수...
:
: socket / process
:
:
: 질문이 애매 모할수 잇는데요.. 일단 OS별로 차이가 잇을거라 생각하고..
:
: 머신의 능력의 차이가 잇을거라 생각합니다...
:
: fork를 할때 fork에러를 일으키는 한도를 정확히 측정 하려고 하는데...
:
: 하나의 프로그램이 무한히 포크를 하다가 에러를 내는것은 1프로세스가 자식을 몇개를 생성 하는가?
:
: 만약 1000개 만들고 더이상 못 할때...
:
: 이 프로그램을 동시에 두개를 돌렸는데 두개 모두 1000개를 만든다면..
:
: 이건 머신에 한계프로세스에 도달한계아니고 한프로세스가 생성하는 자식 프로세스의 한계에
:
: 도달했다고 할수 잇죠...
:
: 이런 일련의 이상 야릇한 호기심이 생겻는데..
:
: 이런 것에 대한 명괘한 답을 찾을수가 없네요..
:
: 일단 플렛폼은 리눅스고요.. ㅎㅎ
:
: 소스를 첨부하는데요...
:
: 서버는 두가지 프로세스 모델과 스레드 모델로서.. 에코기능을 하는 에코 서버입니다.
:
: 모드 리퀘스트 마다 프로세스를 생성해서 또는 스레드를 생성해서 처리합니다..
:
: 클라이언트는 시뮬레이터로 동시에 수많은 클라이언트 생성을 위해 프로세스 모델입니다...
:
: 이런 테스트 중에 생긴 한계프로세스 생성과 한계 스레드 생성 한계 소켓 생성에 대한
:
: 이상 야릇한 질문이엇음다..
:
:
:
: ps /
:
: LInux / Kylix 게시판 에 게제할까 Turbo C/ Borland C++에 게시할까 고민하다가..
: 자게에서 여러 개발자님들의 경험을 듣고 시퍼서 이곳에 올립니다..
: 이점 양해 해주세요...
:
:
:
:
:
:
:
:
:
:
:
|