performance/memory.c

///////////////////////////////////////////////////////////////////////////////
// Filename: memory.c
///////////////////////////////////////////////////////////////////////////////
// Purpose: measure the throughput of memory in normal memory and shared
//          memory
///////////////////////////////////////////////////////////////////////////////
// History:
// ========
//
// Date     Time     Name      Description   
// -------- -------- --------  ------------------------------------------------
// 96/03/17 02:33:04 muellerg: created
//
///////////////////////////////////////////////////////////////////////////////


// Feature test switches ///////////////////////////// Feature test switches //
    /* NONE */



// System headers /////////////////////////////////////////// System headers //

#include <stdlib.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/shm.h>



// Local headers ///////////////////////////////////////////// Local headers //

#include "../common.h"



// Macros /////////////////////////////////////////////////////////// Macros //

// #define READMEMORY 1 
                        /* most compilers fool this test, as they optimize
                           the operations so that the results are not
                           meaningful. The assembler source code was
                           checked that this is not the case for the write */



// File scope objects /////////////////////////////////// File scope objects //

const int NUMBER_REPEAT = 100;          // how often to do measurements

const int SHM_SIZE = 1024*1024;         // shared and normal memory size, 1 MB

const int SHM_MODE = (SHM_R | SHM_W);   // user read/write


// External variables, functions, and classes ///////////// External objects //
    /* NONE */



// Signal catching functions ///////////////////// Signal catching functions //
    /* NONE */



// Structures, unions, and class definitions /////////////////// Definitions //
    /* NONE */




// Functions and class implementation /// Functions and class implementation //

/*
 * perform measurements with memory pointed to by ptr
 */

void writememory(char *ptr, char *prgname, char *comment)
{
    register long *mem;
    register long i = 0;
    register long value = 0;

    measurement mes(prgname, "write", NUMBER_REPEAT);

    int numberoftimes = SHM_SIZE/(sizeof(long) * 64);

    // make sure that memory is attached and eventually partly cached

    for(char *p=ptr; i < SHM_SIZE; i++)
        p[i]=255;   

#ifdef READMEMORY
    cout << "\nWrite to memory" << endl;
#endif

    for(int n=0; n < NUMBER_REPEAT; n++)
    {
        mem = (long *)ptr;
        mes.start(-1, 0, comment);

        // a little bit of loop unrolling

        // this writes 256 bytes if sizeof(long) is 4 bytes
    
        for(i=0; i < numberoftimes; i++)
        {
            *mem++= value; *mem++= value; *mem++= value; *mem++= value;
            *mem++= value; *mem++= value; *mem++= value; *mem++= value;
            *mem++= value; *mem++= value; *mem++= value; *mem++= value;
            *mem++= value; *mem++= value; *mem++= value; *mem++= value;
            *mem++= value; *mem++= value; *mem++= value; *mem++= value;
            *mem++= value; *mem++= value; *mem++= value; *mem++= value;
            *mem++= value; *mem++= value; *mem++= value; *mem++= value;
            *mem++= value; *mem++= value; *mem++= value; *mem++= value;

            *mem++= value; *mem++= value; *mem++= value; *mem++= value;
            *mem++= value; *mem++= value; *mem++= value; *mem++= value;
            *mem++= value; *mem++= value; *mem++= value; *mem++= value;
            *mem++= value; *mem++= value; *mem++= value; *mem++= value;
            *mem++= value; *mem++= value; *mem++= value; *mem++= value;
            *mem++= value; *mem++= value; *mem++= value; *mem++= value;
            *mem++= value; *mem++= value; *mem++= value; *mem++= value;
            *mem++= value; *mem++= value; *mem++= value; *mem++= value;
        }

        mes.end();
    }

    mes.writeout_histogram(true);

#ifdef READMEMORY
    measurement mes2(prgname, "read", NUMBER_REPEAT);
    
    cout << "\nRead from memory" << endl;

    for(int n=0; n < NUMBER_REPEAT; n++)
    {
        mem = (long *)ptr;
        mes2.start(-1, 0, comment);

        // a little bit of loop unrolling

        // this reads 256 bytes if sizeof(long) is 4 bytes
    
        for(i=0; i < numberoftimes; i++)
        {
            value= *mem++; value= *mem++; value= *mem++; value= *mem++; 
            value= *mem++; value= *mem++; value= *mem++; value= *mem++; 
            value= *mem++; value= *mem++; value= *mem++; value= *mem++; 
            value= *mem++; value= *mem++; value= *mem++; value= *mem++; 
            value= *mem++; value= *mem++; value= *mem++; value= *mem++; 
            value= *mem++; value= *mem++; value= *mem++; value= *mem++; 
            value= *mem++; value= *mem++; value= *mem++; value= *mem++; 
            value= *mem++; value= *mem++; value= *mem++; value= *mem++; 

            value= *mem++; value= *mem++; value= *mem++; value= *mem++; 
            value= *mem++; value= *mem++; value= *mem++; value= *mem++; 
            value= *mem++; value= *mem++; value= *mem++; value= *mem++; 
            value= *mem++; value= *mem++; value= *mem++; value= *mem++; 
            value= *mem++; value= *mem++; value= *mem++; value= *mem++; 
            value= *mem++; value= *mem++; value= *mem++; value= *mem++; 
            value= *mem++; value= *mem++; value= *mem++; value= *mem++; 
            value= *mem++; value= *mem++; value= *mem++; value= *mem++; 
        }

        mes2.end();
    }

    mes2.writeout_histogram(true);
#endif /* READMEMORY */

}



// Main /////////////////////////////////////////////////////////////// Main //


int
main(int argc, char *argv[])
{
    error.set_program_name(argv[0]);    

    cout << "This program measures the throughput of normal and shared memory."
         << "\nAll measurements are done " << NUMBER_REPEAT << " times with "
         << "memory regions\nof the size " << SHM_SIZE << " bytes.\n" << endl;


    // two measurements: one in normal memory, one in shared


    // normal memory

    char *mem= new char[SHM_SIZE];

    writememory(mem, argv[0], "Normal Memory:");

    delete[] mem;


    cout << endl;


    // shared memory

    int shmid;  
    char *shmptr;

    // get shared memory region

    if ((shmid = shmget(IPC_PRIVATE, SHM_SIZE, SHM_MODE)) == -1)
        error.system("shmget error");

    if ((shmptr = (char *)shmat(shmid, 0, 0)) == (char *)-1)
        error.system("shmat error");

    writememory(shmptr, argv[0], "Shared memory:");         

    // destroy shared memory region

    if (shmdt(shmptr) == -1)
        error.system("shmdt error");
        
    if (shmctl(shmid, IPC_RMID, 0) == -1)
        error.system("shmctl error");

    return(EXIT_SUCCESS);
}