Проблема размера стека по умолчанию в NPTL - PullRequest
1 голос
/ 04 декабря 2009

Я занимаюсь разработкой многопоточного модульного приложения с использованием языка программирования C и NPTL 2.6 . Для каждого плагина создается поток POSIX. Проблема в том, что каждый поток имеет свою собственную область стека, поскольку размер стека по умолчанию зависит от выбора пользователя, в некоторых случаях это может привести к огромному потреблению памяти.

Чтобы предотвратить ненужное использование памяти, я использовал что-то подобное для изменения размера стека перед созданием каждого потока:

pthread_attr_t attr;
pthread_attr_init (&attr);
pthread_attr_getstacksize(&attr, &st1);
if(pthread_attr_setstacksize (&attr, MODULE_THREAD_SIZE) != 0) perror("Stack ERR");
pthread_attr_getstacksize(&attr, &st2); 
printf("OLD:%d, NEW:%d - MIN: %d\n", st1, st2, PTHREAD_STACK_MIN);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
/* "this" is static data structure that stores plugin related data */
pthread_create(&this->runner, &attr, (void *)(void *)this->run, NULL);

ПРАВКА I: добавлен раздел pthread_create ().

Это не сработало, как я ожидал, размер стека, сообщенный pthread_attr_getstacksize(), изменился, но общее использование памяти приложением (из вывода ps / top / pmap) не изменилось:

СТАРЫЙ: 10485760, НОВЫЙ: 65536 - МИНУТА: 16384

Когда я использую ulimit -s MY_STACK_SIZE_LIMIT перед запуском приложения, я получаю ожидаемый результат.

Мои вопросы:

1-) Существует ли какой-либо переносимый (между вариантами UNIX) способ изменения (по умолчанию) размера стека потока после запуска приложения (конечно, до создания потока)?

2-) Можно ли использовать одну и ту же область стека для каждого потока?

3-) Возможно ли полностью отключить стек для потоков без особой боли?

Ответы [ 2 ]

2 голосов
/ 04 декабря 2009

Ответы для № 2 и № 3 - нет и нет. Каждому потоку нужен стек (куда еще идут ваши локальные переменные и адреса возврата?), И они должны быть уникальными для каждого потока (в противном случае потоки перезаписывают локальные переменные и адреса возврата друг друга, что приводит к сбою всех).

Что касается # 1 ... вызов установленного размера стека является именно тем ответом. Я предлагаю вам определить приемлемый размер для создания ваших тем и установить его.

Что касается того, почему в top .... все выглядит неправильно, top является печально известным лжецом об использовании памяти. :-) Неужели вещи не распределяются или не убиваются OOM? Не удалось создать поток? Производительность страдает и страничка на диск увеличивается? Если ответ на эти вопросы - «нет», то мне не о чем беспокоиться.

Обновление на основе некоторых комментариев ниже и выше:
Во-первых, 16 КБ все еще достаточно велики для того, что, как вы говорите, не требует много места в стеке. Если вы действительно хотите стать маленьким, я бы хотел сказать 4096 или 8192 на x86 Linux. Во-вторых, да, вы можете установить указатель стека вашего процессора на что-то еще ... Но когда вы malloc() или mmap(), это займет место. Я не знаю, как вы думаете, это поможет установить указатель стека на что-то еще. Тем не менее, если вы действительно чувствуете, что поток, вызывающий main(), имеет слишком большой стек (я бы сказал, что это немного сумасшедший) и что pthread_attr_setstacksize() не позволяет вам стать достаточно маленьким (?), То, возможно, Вы можете посмотреть на непереносимые вещи, такие как создание потоков, вызвав системный вызов <a href="http://linux.die.net/man/2/clone" rel="nofollow noreferrer">clone()</a> и указав стеки на основе указателя стека основного потока, или буфера из другого места, или чего-то еще. Но вам все еще понадобится стек для каждого потока, и я чувствую, что top все равно вас разочарует. Может быть, ваши ожидания немного высоки.

1 голос
/ 15 мая 2010

Я тоже видел эту проблему. Непонятно, как учитываются стеки, но «лишнее» пространство засчитывается в общую виртуальную машину, и если вы столкнетесь с границей процесса, у вас возникнут проблемы (даже если вы не используете пространство). Кажется, это зависит от того, какую версию Linux вы используете (даже в пределах семейства 2.6), и от того, 32-битная или 64-битная версия.

...