본문 바로가기

UNIX_LINUX_C_C++

Linux 에서 pthread를 최대 생성가능한 thread 수를 측정

원문: http://minzkn.wowdns.com:2744/phpBB2/viewtopic.php?t=582



이 소스는 그냥 Linux 에서 pthread를 이용하였을때 최대 생성가능한 thread 수를
단순한 방법론으로 측정하는겁니다.

제 Desktop PC는 최대 382 개가 나오는군요. (에게~ 요것밖에 안되~? ㅋㅋ)
하지만 소스상에서 stack size를 어떻게 사용하는가에 따라서 시스템에 황금비율의 최대 생성갯수를 얻을수 있는 경우가 있습니다. 각자 그 부분은 해보시면 흥미로운 결과를 체험할수 있을거란 생각이 드는군요.

main.c

코드:
/*
Copyright (C) Information Equipment co.,LTD.
All rights reserved.
Code by JaeHyuk Cho <mailto:minzkn@infoeq.com>
CVSTAG="$Header$"
*/

#if !defined(__def_mzapi_source_main_c__)
#define __def_mzapi_source_main_c__ "main.c"

#include <sys/types.h>
#include <sys/time.h>
#include <limits.h>
#include <stdio.h>
#include <unistd.h>

#include <pthread.h>

#define def_i386_cpu (1)
#define def_max_test (64 << 10)
#define def_stack_size (PTHREAD_STACK_MIN)

struct ts_thread_context { volatile int stop, thread_count; };

static int atomic_read_return(int volatile *s_ptr)
{
register int s_value;
#if def_i386_cpu != (0)
__asm__ __volatile__("movl 0(%1), %0\n\t":"=r"(s_value):"0"(s_ptr):"memory","eax");
#else
s_value = *s_ptr;
#endif
return(s_value);
}

static void (load_balance)(void)
{
struct timeval s_timeval = { (long)0, (long)(10 * 1000) }; /* 1000 / USER_HZ(i386) = 10ms */
(void)select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, (struct timeval *)(&s_timeval));
}

static void * (simple_thread)(void *s_argument)
{
#if def_i386_cpu != (0)
__asm__ __volatile__("lock incl 0(%0)\n\t"::"r"(&((struct ts_thread_context *)s_argument)->thread_count));
#else
++((struct ts_thread_context *)s_argument)->thread_count;
#endif
while(atomic_read_return(&((struct ts_thread_context *)s_argument)->stop) == 0)load_balance();
#if def_i386_cpu != (0)
__asm__ __volatile__("lock decl 0(%0)\n\t"::"r"(&((struct ts_thread_context *)s_argument)->thread_count));
#else
--((struct ts_thread_context *)s_argument)->thread_count;
#endif
return(NULL);
}

int main(void)
{
struct ts_thread_context s_context = {0, 0, };
pthread_t s_thread;
pthread_attr_t s_pthread_attr;
int s_count = 0, s_check;

if(pthread_attr_init((pthread_attr_t *)(&s_pthread_attr)) == 0)
{
size_t s_stack_size;
if(pthread_attr_getstacksize((pthread_attr_t *)(&s_pthread_attr), (size_t *)(&s_stack_size)) == 0)
{
(void)fprintf(stdout, "default stack size is %lu Kbytes (%lu bytes, min=%lu)\n", (unsigned long)(s_stack_size >> 10), (unsigned long)s_stack_size, (unsigned long)def_stack_size);
}
(void)pthread_attr_destroy((pthread_attr_t *)(&s_pthread_attr));
}
do
{
s_check = pthread_attr_init((pthread_attr_t *)(&s_pthread_attr));
if(s_check != 0)
{
(void)fprintf(stdout, "pthread_attr_init error\n");
continue;
}
s_check = pthread_attr_setstacksize((pthread_attr_t *)(&s_pthread_attr), (size_t)(def_stack_size));
if(s_check != 0)
{
(void)fprintf(stdout, "pthread_attr_serstacksize error\n");
}
s_check = pthread_attr_setdetachstate((pthread_attr_t *)(&s_pthread_attr), PTHREAD_CREATE_DETACHED);
if(s_check == 0)s_check = pthread_create((pthread_t *)(&s_thread), (pthread_attr_t *)(&s_pthread_attr), simple_thread, (void *)(&s_context));
(void)pthread_attr_destroy((pthread_attr_t *)(&s_pthread_attr));
}while((s_check == 0) && ((s_count++) < def_max_test));
s_context.stop = 1;
(void)fprintf(stdout, "thread_max = %d\n", s_count);
while(atomic_read_return(&s_context.thread_count) > 0)load_balance();
(void)fprintf(stdout, "\nend.\n");
return(0);
}

#endif

/* vim: set expandtab: */
/* End of source */


Makefile
코드:
# Copyright (C) Information Equipment co.,LTD
# All rights reserved.
# Code by JaeHyuk Cho <mailto:minzkn@infoeq.com>
# CVSTAG="$Header$"

# bash$ make TARGET_ARCH=i386 all
# bash$ make TARGET_ARCH=mips all
# bash$ make TARGET_ARCH=ppc all
# bash$ make TARGET_ARCH=arm all

TARGET_ARCH :=i386
# TARGET_ARCH :=mips
# TARGET_ARCH :=ppc
# TARGET_ARCH :=arm

ifeq ($(findstring mips,$(TARGET_ARCH)),mips)
CROSS_COMPILE ?=/opt/kenati/bin/lx4189-uclibc-#
endif
ifeq ($(findstring ppc,$(TARGET_ARCH)),ppc)
CROSS_COMPILE ?=/opt/hardhat/devkit/ppc/405/bin/ppc_405-#
endif
ifeq ($(findstring arm,$(TARGET_ARCH)),arm)
CROSS_COMPILE ?=/usr/local/arm-linux/bin/arm-linux-#
endif

# default
CROSS_COMPILE ?=#

CC := $(CROSS_COMPILE)gcc
AR := $(CROSS_COMPILE)ar
RM := rm -f

THIS_NAME := mzthread_max

CFLAGS := -O2
# CFLAGS += -g
CFLAGS += -Wall
CFLAGS += -Werror
CFLAGS += -fomit-frame-pointer
CFLAGS += -fPIC
CFLAGS += -pipe
#CFLAGS += -ansi
CFLAGS += -I.
CFLAGS += -D_REENTRANT

LDFLAGS := -s -lpthread#
ARFLAGS := rc#

TARGET_bin := $(THIS_NAME)
TARGET := $(TARGET_bin)

OBJECTS_bin := main.o
OBJECTS := $(OBJECTS_bin)

.PHONY: all clean

all: $(TARGET)
clean: ; $(RM) *.o $(TARGET)

$(TARGET_bin): $(OBJECTS_bin) ; $(CC) $(LDFLAGS) -o $(@) $(^)

$(OBJECTS): Makefile

%.o: %.c ; $(CC) $(CFLAGS) -c -o $(@) $(<)

# End of Makefile