CreateThread и dwStackSize
От: found Россия ak239.ru
Дата: 24.02.12 21:20
Оценка: 5 (2)
Здравствуйте.

В Университете задали лабораторную работу, в процессе выполнения которой необходимо создать, как можно больше потоков с помощью функции CreateThread.
(Отлично осознаю, что задача абсолютно искусственна и при реальной необходимости лучше воспользоваться Threadpool, либо IO)

Первое ограничение на количество потоков накладывает отношение размера адресного пространства всего потока к размеру стека процесса. Размер стека, создаваемого потока, задается отсюда:
To change the initially committed stack space, use the dwStackSize parameter of the CreateThread, CreateRemoteThread, or CreateFiber function. This value is rounded up to the nearest page.

Перелопатил множество статей о других ограничениях, лучшей из которых могу назвать следующую: "Преодолевая границы Windows: процессы и потоки". Она является переводом статьи Марка Руссиновича.

Но к необходимости много искать в интернете меня привел следующий код:
  ...
  for (int i = 0; i < MAX; i++){
    handles[i] = CreateThread(NULL, 1, ThreadProc, NULL, STACK_SIZE_PARAM_IS_A_RESERVATION , NULL);
    ...


В моем представлении, которое опирается на документацию, в данном случае стек потока должен быть равен 64 КБ (размеру страницы в целевой системе — Windows 7 SP1). На деле же, согласно vmmap получается следующая картина:


Утилита, которая используется в статье Марка: testlimit с ключами -t -n(задает минимальный размер стека). Так же выделяет блоки стека по 1024 Кб, вместо 64 Кб.

В операционных системах Windows 2003 Server и Windows XP код, приведенный выше, создает потоки с размером стека равным 64 Кб. Для запуска в системы устанавливался пакет VS 2010 C++ Redist.

После тестирования в других ОС мне в голову пришла крамольная мысль об ошибке внутри самой Windows 7, потому что после ряда тестов, удалось выявить следующую закономерность:
Код:
    handles[i] = CreateThread(NULL, 4096, ThreadProc, NULL, STACK_SIZE_PARAM_IS_A_RESERVATION , NULL);

Создает поток с размером стека в 1 Мб (значение по умолчанию).

Код:
    handles[i] = CreateThread(NULL, 4097, ThreadProc, NULL, STACK_SIZE_PARAM_IS_A_RESERVATION , NULL);

Создает поток с размером стека в 64 Кб (ближайшая страница).

Дальнейшие опыты показали, что при значения dwStackSize 0 — применяется значение по умолчанию, от 1 до 4096 значение по умолчанию, от 4097 до 65536 — 64 Кб, при 65537 — 128 Кб. Что наталкивает на мысль об ошибке округления внутри функции, находящейся в ядре ОС, и отвечающей за создание потоков.

Резюмирую список вопросов:
1. Действительно ли при 0 < dwStackSize <= 64 Кб должно резервироваться 64 Кб?
2. Пакеты для Microsoft Visual C++ X Redistributable Package являются ли прослойкой между приложением и вызовом системных функций, либо же функции WinAPI, к примеру, CreateThread вызываются напрямую?
3. Если же имеет место ошибка в функции WinAPI, куда можно писать баг репорт?

Спасибо, за внимание. Мой первый пост на rsdn, выслушаю любую критику по оформлению.
createthread stack size winapi
Re: CreateThread и dwStackSize
От: Banned by IT  
Дата: 24.02.12 22:48
Оценка:
Здравствуйте, found, Вы писали:

F>1. Действительно ли при 0 < dwStackSize <= 64 Кб должно резервироваться 64 Кб?

Согласно документации должен резервироваться объём, кратный размеру system allocation granularity.
У меня на W2008R2 x64 GetSystemInfo возвращает dwAllocationGranularity == 65536 байт, что совпадает с написанным в MSDN.

F>2. Пакеты для Microsoft Visual C++ X Redistributable Package являются ли прослойкой между приложением и вызовом системных функций, либо же функции WinAPI, к примеру, CreateThread вызываются напрямую?

Напрямую.

F>3. Если же имеет место ошибка в функции WinAPI, куда можно писать баг репорт?

Я бы для начала попробовал бы сделать наглядные примеры и попытался бы написать на форум к Руссиновичу.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Забанили по IP, значит пора закрыть эту страницу.
Всем пока
Re: CreateThread и dwStackSize
От: ononim  
Дата: 25.02.12 12:33
Оценка:
Резервирование размера не кратного allocation granularity — бессмысленно. Ибо все равно эффективно отожрет те же n*64к памяти.
Как много веселых ребят, и все делают велосипед...
Re[2]: CreateThread и dwStackSize
От: о_О
Дата: 25.02.12 12:37
Оценка:
Здравствуйте, ononim, Вы писали:

наверное эффект нового менеджера памяти в 6м ядре
Re[2]: CreateThread и dwStackSize
От: found Россия ak239.ru
Дата: 25.02.12 16:50
Оценка:
Здравствуйте, ononim, Вы писали:

O>Резервирование размера не кратного allocation granularity — бессмысленно. Ибо все равно эффективно отожрет те же n*64к памяти.


Понимаю это, единичку выставляю, чтобы как раз получить самый маленький возможный стек, а на деле 1 — 4096 округляется до 1 Мб, а 4097 — 64 Кб до 64 Кб.
Re[3]: CreateThread и dwStackSize
От: ZOI4  
Дата: 29.02.12 21:28
Оценка:
Здравствуйте, found, Вы писали:

F>Здравствуйте, ononim, Вы писали:


O>>Резервирование размера не кратного allocation granularity — бессмысленно. Ибо все равно эффективно отожрет те же n*64к памяти.


F>Понимаю это, единичку выставляю, чтобы как раз получить самый маленький возможный стек, а на деле 1 — 4096 округляется до 1 Мб, а 4097 — 64 Кб до 64 Кб.


Это наверное происходит потому, что размер страницы 4 Кб, а для стека нужно минимум 2 страницы — вторая отмечает его границу и не используется. Поэтому видя, что заданный параметр некорректен, функция использует дефолтное значение.
Мафиозная диктатура это нестабильность. Если не мафиозная диктатура, то Конституция и демократия.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.