memstress/src/mem_stress.cpp
// main thread doing the job. beviour depends on config collected from
// command line arguments
main thread doing the job. beviour depends on config collected from
command line arguments
main thread doing the job . beviour depends on config collected from command line arguments
void* worker_thread(void *arg)
{
    pthread_t id = pthread_self();
    clock_t starttime = clock();
    printf("thread id is : %lu\n", id);
    long long loop_size = config.total_alloc_size/config.num_threads/config.alloc_block_size;
    printf("loop size is %lld with each alloation %lu MB\n", loop_size, config.alloc_block_size/1024/1024);
    unsigned long long int allocation_counter = 0;
    srand(time(NULL));  
     void ** memory_tracker = (void **)calloc(loop_size, sizeof(void *));
    for( int i = 0; i < loop_size; i++)
    {
        if (config.run_till_death) {
            i--; 
        }
        void * mem = malloc(config.alloc_block_size);
        if(!mem) {
            printf("are we out of memory? shouldn't default overcommit policy allow for always non zero and oom lateron?");
            fflush(stdout);
            exit(-1);
        }
        memory_tracker[i] = mem;
        if (config.write_random_data) {
            unsigned int int_counts = config.alloc_block_size/4;
            int *write_ptr=(int*)mem;
            for (unsigned int i = 0; i < int_counts; i++)
            {
                *write_ptr = rand();
                write_ptr++;
            }
        } else {
            memset(mem, 'a', config.alloc_block_size);
        }
        allocation_counter += config.alloc_block_size;
        if (config.run_till_death) {
            printf("%llu\n",allocation_counter);
            fflush(stdout);
        }
        if (config.sleep_bw_ops)
            usleep(config.sleep_bw_ops);
        else
            pthread_yield();
    }
    unsigned int thread_index = *((unsigned int *)arg);
    thread_tracker[thread_index].ticks_taken = clock() - starttime;
    thread_tracker[thread_index].size = allocation_counter;
    if (config.keep_mem_hot) {
        while(1) { 
            clock_t hot_timer_start = clock();
            for( int i = 0; i < loop_size; i++)
            {
                if (config.write_random_data) {
                    unsigned int int_counts = config.alloc_block_size/4;
                    int *write_ptr=(int*)memory_tracker[i];
                    for (unsigned int i = 0; i < int_counts; i++)
                    {
                        *write_ptr = rand();
                        write_ptr++;
                    }
                } else {
                    memset(memory_tracker[i], 'a', config.alloc_block_size);
                }
                usleep(config.keep_mem_hot);
            }
            thread_tracker[thread_index].hot_ticks_taken = clock() - hot_timer_start;
            float time_in_secs = ((long double)thread_tracker[thread_index].hot_ticks_taken)/CLOCKS_PER_SEC;
            printf("HOT mem(bytes):%llu time(secs):%f speed(mbps):%f\n",
                   thread_tracker[thread_index].size, time_in_secs, thread_tracker[thread_index].size/1024/1024/time_in_secs);
        }
    }
    pthread_mutex_lock(&cond_var_lock);
    pthread_cond_signal(&cond_var);
    pthread_mutex_unlock(&cond_var_lock);
    return NULL;
}
void * worker_thread ( void * arg ) { pthread_t id = pthread_self ( ) ; clock_t starttime = clock ( ) ; printf ( " \n " , id ) ; long long loop_size = config . total_alloc_size / config . num_threads / config . alloc_block_size ; printf ( " \n " , loop_size , config . alloc_block_size / 1024 / 1024 ) ; unsigned long long int allocation_counter = 0 ; srand ( time ( NULL ) ) ; void * * memory_tracker = ( void * * ) calloc ( loop_size , sizeof ( void * ) ) ; for ( int i = 0 ; i < loop_size ; i ++ ) { if ( config . run_till_death ) { i -- ; } void * mem = malloc ( config . alloc_block_size ) ; if ( ! mem ) { printf ( " " ) ; fflush ( stdout ) ; exit ( -1 ) ; } memory_tracker [ i ] = mem ; if ( config . write_random_data ) { unsigned int int_counts = config . alloc_block_size / 4 ; int * write_ptr = ( int * ) mem ; for ( unsigned int i = 0 ; i < int_counts ; i ++ ) { * write_ptr = rand ( ) ; write_ptr ++ ; } } else { memset ( mem , ' ' , config . alloc_block_size ) ; } allocation_counter += config . alloc_block_size ; if ( config . run_till_death ) { printf ( " \n " , allocation_counter ) ; fflush ( stdout ) ; } if ( config . sleep_bw_ops ) usleep ( config . sleep_bw_ops ) ; else pthread_yield ( ) ; } unsigned int thread_index = * ( ( unsigned int * ) arg ) ; thread_tracker [ thread_index ] . ticks_taken = clock ( ) - starttime ; thread_tracker [ thread_index ] . size = allocation_counter ; if ( config . keep_mem_hot ) { while ( 1 ) { clock_t hot_timer_start = clock ( ) ; for ( int i = 0 ; i < loop_size ; i ++ ) { if ( config . write_random_data ) { unsigned int int_counts = config . alloc_block_size / 4 ; int * write_ptr = ( int * ) memory_tracker [ i ] ; for ( unsigned int i = 0 ; i < int_counts ; i ++ ) { * write_ptr = rand ( ) ; write_ptr ++ ; } } else { memset ( memory_tracker [ i ] , ' ' , config . alloc_block_size ) ; } usleep ( config . keep_mem_hot ) ; } thread_tracker [ thread_index ] . hot_ticks_taken = clock ( ) - hot_timer_start ; float time_in_secs = ( ( long double ) thread_tracker [ thread_index ] . hot_ticks_taken ) / CLOCKS_PER_SEC ; printf ( " \n " , thread_tracker [ thread_index ] . size , time_in_secs , thread_tracker [ thread_index ] . size / 1024 / 1024 / time_in_secs ) ; } } pthread_mutex_lock ( & cond_var_lock ) ; pthread_cond_signal ( & cond_var ) ; pthread_mutex_unlock ( & cond_var_lock ) ; return NULL ; }
main thread doing the job.
main thread doing the job .
// allocation loop // init random number generator // need to allocate some memory to keep track of our allocated block // we are not accounting for memory allocated for this tracker. // this might impact measurement results when using smaller alloc sizes. // preprae for loop till death // loop will run forever // track allocated memory for later hot loop // we need memset because just like malloc, calloc also cheats and will succeed even if we // don't have that memory. As we will be testing compressed memory/swap options, lets take // this opporitunity to fill it with random numbers. // zero or constant fill has too little entropy and will have insanely large compression ratio // real data will be closer to random that a bunch of zeros // yeild after every allocation, so that all threads are roughly moving at the same pace. // we can have configurtion per thread if we ever need differene allocation speeds // store the stats in this threads struct // keep the memory hot // keep hot forever // signal the main thread that we are done