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);
}