CodeZine(コードジン)

特集ページ一覧

pthreadについて(スタックサイズ)

スタックサイズの変更と、起動スレッド数の関係

  • LINEで送る
  • このエントリーをはてなブックマークに追加
2008/01/18 14:00
目次

8. スレッド属性(スレッド数)

8.4 起動スレッド数との関連

 どんなに贅沢な環境であっても、メモリは有限です。有限である以上、プロセスが使用できるメモリ量はスタックに上限があります。

 カーネルでは10,000個以上のスタックを生成できる設定になっていてもメモリが十分でなければ生成スレッド数はそれ以下になります。スレッドが起動できない理由はエラーコードから判定することができます。

  • エラーコードが11(Resource temporarily unavailable)
  • 生成可能スレッドの最大値に達した事を表しています。
  • エラーコードが12(Cannot allocate memory)
  • 最大値に達する前にスタックでメモリを食いつぶした事を表しています。

 以下のサンプルを起動する事で、スタックサイズの遷移によって起動可能スレッド数が変わっていくのが判ると思います。

stack_thread.c
/* gcc stack_thread.c -o stack_thread -W -Wall -g -lpthread */
#include <stdio.h>
#include <string.h>
#include <pthread.h>
#include <errno.h>
#include <unistd.h>
#include <limits.h>

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t  cond  = PTHREAD_COND_INITIALIZER;

void create_thread( size_t size );
void * thread_func( void * arg );

int main( ) {
    pthread_attr_t attr;
    size_t         stack_size = 0;

    pthread_attr_init( &attr );
    pthread_attr_getstacksize( &attr, &stack_size );

    create_thread( PTHREAD_STACK_MIN );
    create_thread( PTHREAD_STACK_MIN * 4 );
    create_thread( stack_size );
    create_thread( stack_size * 32 );
    create_thread( stack_size * 128 );
    create_thread( stack_size * 256 );

    return 0;
}

void create_thread( size_t size ) {

    pthread_attr_t attr;
    pthread_t   id;
    int         status = 0;
    int         i = 0;

    pthread_attr_init( &attr );
    pthread_attr_setstacksize( &attr, size );

    for( i = 0; ; i ++ ) {
        status = pthread_create(
            &id, &attr, thread_func, ( void * )&i );
        if( status ) {
            pthread_cond_broadcast( &cond );
            break;
        }
    }
    printf( "stack size %zd[%zdK], total size %zd[%zdM], "
        "total thread_count %d\n",
        size, size >> 10, size * i, ( size * i ) >> 20, i );
    printf( "   pthread_create error. [%d][%s]\n",
        status, strerror( status ));
    pthread_attr_destroy( &attr );
    sleep( 1 );
    return;
}

void * thread_func( void * arg ) {
    ( void )arg;

    pthread_detach( pthread_self( ));

    pthread_mutex_lock( &mutex );
    pthread_cond_wait( &cond, &mutex );
    pthread_mutex_unlock( &mutex );

    return 0;
}

 私の環境では、下記の通りとなりました。

guest $ ./stack_thread
stack size 16384[16k], total size 200163328[190M], 
total thread_count 12217
   pthread_create error. [11][Resource temporarily unavailable]
stack size 65536[64k], total size 800653312[763M], 
total thread_count 12217
   pthread_create error. [11][Resource temporarily unavailable]
stack size 10485760[10240k], total size -1149239296[3000M], 
total thread_count 300
   pthread_create error. [12][Cannot allocate memory]
stack size 335544320[327680k], total size -1610612736[2560M], 
total thread_count 8
   pthread_create error. [12][Cannot allocate memory]
stack size 671088640[655360k], total size 2013265920[1920M], 
total thread_count 3
   pthread_create error. [12][Cannot allocate memory]
stack size 1342177280[1310720k], total size 1342177280[1280M], 
total thread_count 1
   pthread_create error. [12][Cannot allocate memory]
guest $
guest $ cat /proc/sys/kernel/threads-max
24572
guest $

 上記から、私の環境ではスタックサイズを16~64Kくらいだと、threads-maxの半値、つまり生成スレッドの最大値になります。デフォルトのスタックサイズではスレッド数は300個、スタックサイズを320Mまであげると8個、1.2Gまで上げると3個です。

8.5 所感

 以上でスレッド属性の簡単な説明を終えます。スタックサイズを小さくして大量のスレッドを生成する場合、スタックのデフォルト値でスレッドの上限値に達するような環境の場合は、その効果は期待できません(私の環境では大いに改善しましたが)。

 スレッド内で大量のメモリを消費する可能性がある場合、もしくはスタックサイズを縮める事で起動可能スレッド数を増やしたい場合に使用のが良いでしょう(それ以前にメモリを積めって話もありますが…)。

 次回はスレッド属性におけるスケジューリングとその影響について述べます。



  • LINEで送る
  • このエントリーをはてなブックマークに追加

バックナンバー

連載:pthreadについて

もっと読む

著者プロフィール

  • 赤松 エイト(エイト)

    (株)DTSに勤てます。 WebアプリやJavaやLL等の上位アプリ環境を密かに憧れつつも、ず~っとLinuxとかHP-UXばかり、ここ数年はカーネル以上アプリ未満のあたりを行ったり来たりしています。 mixiもやってまして、こちらは子育てとか日々の日記メインです。

あなたにオススメ

All contents copyright © 2005-2022 Shoeisha Co., Ltd. All rights reserved. ver.1.5