Bonita Montero
2020-04-14 07:08:49 UTC
I've written a little test-program that shows that Windows
has overcommitting, but only for stacks:
#include <Windows.h>
#include <Psapi.h>
#include <iostream>
#include <vector>
#include <thread>
#include <malloc.h>
using namespace std;
#pragma warning(disable: 6255) // alloca might stack overflow
#pragma warning(disable: 6031) // return value ignored
int main()
{
auto printPrivateUsage = [&]( char const *str )
{
PROCESS_MEMORY_COUNTERS_EX pmcx;
if( !GetProcessMemoryInfo( GetCurrentProcess(),
(PROCESS_MEMORY_COUNTERS *)&pmcx, sizeof pmcx ) )
return;
cout << (pmcx.PrivateUsage / 1024 / 1024) << str << endl;
};
printPrivateUsage( " MB before 512MB allocated" );
cout << "press return to allocate 512MB" << endl;
getchar();
VirtualAlloc( nullptr, 512 * 1024 * 1024, MEM_RESERVE | MEM_COMMIT,
PAGE_READWRITE );
printPrivateUsage( " MB after memory allocated (pages not touched !)
and before thread created" );
cout << "press return to create threads" << endl;
getchar();
unsigned const N_THREADS = 1000;
HANDLE hSemTouch = CreateSemaphore( NULL, 0, N_THREADS, NULL ),
hSemAllocd = CreateSemaphore( NULL, 0, N_THREADS, NULL ),
hSemGoodbye = CreateSemaphore( NULL, 0, N_THREADS, NULL );
auto thr = [hSemTouch, hSemAllocd, hSemGoodbye]()
{
char a[1];
WaitForSingleObject( hSemTouch, INFINITE );
__try
{
for( char volatile *p = a; ; *p-- );
}
__except( EXCEPTION_EXECUTE_HANDLER )
{
}
ReleaseSemaphore( hSemAllocd, 1, NULL );
WaitForSingleObject( hSemGoodbye, INFINITE );
};
vector<thread> vt;
for( unsigned t = N_THREADS; t; --t )
vt.emplace_back( thr );
printPrivateUsage( " MB after thread created" );
cout << N_THREADS << " threads created; press return to allocate in
thread-stacks" << endl;
getchar();
ReleaseSemaphore( hSemTouch, N_THREADS, NULL );
for( unsigned t = N_THREADS; t; --t )
WaitForSingleObject( hSemAllocd, INFINITE );
printPrivateUsage( " MB after threads have allocated" );
cout << "stacks read; press return terminate threads" << endl;
getchar();
ReleaseSemaphore( hSemGoodbye, N_THREADS, NULL );
for( thread &t : vt )
t.join();
}
has overcommitting, but only for stacks:
#include <Windows.h>
#include <Psapi.h>
#include <iostream>
#include <vector>
#include <thread>
#include <malloc.h>
using namespace std;
#pragma warning(disable: 6255) // alloca might stack overflow
#pragma warning(disable: 6031) // return value ignored
int main()
{
auto printPrivateUsage = [&]( char const *str )
{
PROCESS_MEMORY_COUNTERS_EX pmcx;
if( !GetProcessMemoryInfo( GetCurrentProcess(),
(PROCESS_MEMORY_COUNTERS *)&pmcx, sizeof pmcx ) )
return;
cout << (pmcx.PrivateUsage / 1024 / 1024) << str << endl;
};
printPrivateUsage( " MB before 512MB allocated" );
cout << "press return to allocate 512MB" << endl;
getchar();
VirtualAlloc( nullptr, 512 * 1024 * 1024, MEM_RESERVE | MEM_COMMIT,
PAGE_READWRITE );
printPrivateUsage( " MB after memory allocated (pages not touched !)
and before thread created" );
cout << "press return to create threads" << endl;
getchar();
unsigned const N_THREADS = 1000;
HANDLE hSemTouch = CreateSemaphore( NULL, 0, N_THREADS, NULL ),
hSemAllocd = CreateSemaphore( NULL, 0, N_THREADS, NULL ),
hSemGoodbye = CreateSemaphore( NULL, 0, N_THREADS, NULL );
auto thr = [hSemTouch, hSemAllocd, hSemGoodbye]()
{
char a[1];
WaitForSingleObject( hSemTouch, INFINITE );
__try
{
for( char volatile *p = a; ; *p-- );
}
__except( EXCEPTION_EXECUTE_HANDLER )
{
}
ReleaseSemaphore( hSemAllocd, 1, NULL );
WaitForSingleObject( hSemGoodbye, INFINITE );
};
vector<thread> vt;
for( unsigned t = N_THREADS; t; --t )
vt.emplace_back( thr );
printPrivateUsage( " MB after thread created" );
cout << N_THREADS << " threads created; press return to allocate in
thread-stacks" << endl;
getchar();
ReleaseSemaphore( hSemTouch, N_THREADS, NULL );
for( unsigned t = N_THREADS; t; --t )
WaitForSingleObject( hSemAllocd, INFINITE );
printPrivateUsage( " MB after threads have allocated" );
cout << "stacks read; press return terminate threads" << endl;
getchar();
ReleaseSemaphore( hSemGoodbye, N_THREADS, NULL );
for( thread &t : vt )
t.join();
}