[NCLUG] July 1, 2003 talk - Linux System Performance

jbass at dmsd.com jbass at dmsd.com
Wed Jun 25 11:31:08 MDT 2003


Hi Guys,

At next weeks meeting I will be presenting issues which impact
Linux system performance. Included will be background to understand
the difference between various platforms we run Linux on, VM issues,
and thoughts about workloads and application design. This is a
broad intro to performance assessment, and has aspects for novices
to wizards. Locality, Locality, Locality is the mantra.

This is another old talk of mine, with it's root's in my college days
as a undergraduate seminar talk nearly 30 years ago, updated over time
with changes in the technology.

In preparation for the talk I seek a broad range of current system
data on memory/cache/TLB performance, as well as getting people to
think about the issues before the talk. Please compile and run the
memory/cache/TLB benchmark below and return the results to me with
a description of the system including CPU's, motherboard, chipset,
memory type and size. You might find it interesting to run the test
both single user and multiuser from an xterm. Other interesting
tests are with various I/O active in the background (disk, network,
etc) and multiple sessions on machines with two or more processors.

Will the SVGA projector be there?

See ya next week!

have fun!!
John

----------------------------- Cut Here ---------------------------------------
/*
 * mbench
 * John L. Bass, DMS Design, Copyright 1984-1996
 */
#include <sys/types.h>
#include <sys/times.h>
#include <unistd.h>
#include <limits.h>
#include <stdio.h>

#ifndef CLK_TCK
#define CLK_TCK 100
#endif

unsigned int data[1024*1024*4]; /* 16mb span */

/*
 * Memory access - random - exercise L1, L2 cache plus TLB's.
 * do 32 random memory accesses per count over a range of size words
 */

random(count, size) {

  size /= sizeof (unsigned int);

  while(count-- > 0 && 0xfffffff !=
    data[data[data[data[data[data[data[data[data[data[data[data[data[data[data[
    data[data[data[data[data[data[data[data[data[data[data[data[data[data[data[
    data[data[
      count%size
    ]] ]]]]]]]]]]]]]]] ]]]]]]]]]]]]]]] );
}

/*
 * Memory access - sequential 
 * do 32 sequential cache line accesses per count of a range of size words
 */
sequential(count, size)
unsigned int count, size;
{
    struct cache_lines {
        unsigned int data;
        unsigned int fill[7];
    } *linep, *cachep = (struct cache_lines *) data;

    size /= ((sizeof (struct cache_lines)) * 32);

    while(count-- > 0 && (linep = &cachep[(count%size)*32]) && (
        linep[0x00].data | linep[0x01].data | linep[0x02].data | linep[0x03].data |
        linep[0x04].data | linep[0x05].data | linep[0x06].data | linep[0x07].data |
        linep[0x08].data | linep[0x09].data | linep[0x0a].data | linep[0x0b].data |
        linep[0x0c].data | linep[0x0d].data | linep[0x0e].data | linep[0x0f].data |
        linep[0x10].data | linep[0x11].data | linep[0x12].data | linep[0x13].data |
        linep[0x14].data | linep[0x15].data | linep[0x16].data | linep[0x17].data |
        linep[0x18].data | linep[0x19].data | linep[0x1a].data | linep[0x1b].data |
        linep[0x1c].data | linep[0x1d].data | linep[0x1e].data | linep[0x1f].data
    ) != 0 );
}

/*
 * init_data to random values mod range size
 */

init_data(bytes)
{
    register unsigned int *word;

    srand(1234567);

    for(word=data; word < &data[bytes/sizeof (unsigned int)]; word++) {
	*word = rand() % (bytes/sizeof (unsigned int));
    }
}

/*
 * interate random runs to find the count which matches the number of
 * seconds requested.
 */

unsigned int
do_random(seconds, size) {
    clock_t	real_start,	real_stop;
    struct tms	cpu_start,	cpu_stop;
    static unsigned int current, count, first_time = 1;

    if(first_time) {
        current = CLK_TCK;
        count = 100000;
        first_time = 0;
    }

    init_data(size);

    do {
	count = (CLK_TCK*seconds*count+current/2)/current;
	real_start = times(&cpu_start);
	random(count, size);
	real_stop = times(&cpu_stop);
	current = (real_stop - real_start);
        if(current == 0) current = 1;
    } while (((current+CLK_TCK/2)/CLK_TCK) != seconds);
    return((32*count+current/2)/current);
}

/*
 * interate sequential runs to find the count which matches the number of
 * seconds requested.
 */

unsigned int
do_sequential(seconds, size) {
    clock_t	real_start,	real_stop;
    struct tms	cpu_start,	cpu_stop;
    static unsigned int current, count, first_time = 1;

    if(first_time) {
        current = CLK_TCK;
        count = 100000;
        first_time = 0;
    }

    do {
	count = (CLK_TCK*seconds*count+current/2)/current;
	real_start = times(&cpu_start);
	sequential(count, size);
	real_stop = times(&cpu_stop);
	current = (real_stop - real_start);
        if(current == 0) current = 1;
    } while (((current+CLK_TCK/2)/CLK_TCK) != seconds);
    return((32*count+current/2)/current);
}

/*
 * Search memory speed between 1K and 2M Bytes
 */

main(argc, argv)
int argc;
char *argv[];
{
    unsigned int size, seconds = 10;
    unsigned int rhigh, shigh, rval, sval, phigh;
    int i;
    char plot[46];

printf("Mbench by John. L. Bass, DMS Design copyright 1985-1996\n");
printf("You are free to copy and use this program providing configuration info\n");
printf("and results are shared with the author by email to jbass at dmsd.com\n\n");
printf("Counts are per clock tick, presumed to be HZ=%d\n", CLK_TCK);
printf("SetSize        Random   Sequential\n");
printf("-------  ------------ ------------ 0%%        25%%        50%%        75%%       100%%\n");

    if(argc > 1) seconds = atoi(argv[1]);

    do_random(2, sizeof data);
    do_sequential(2, sizeof data);
    rhigh = shigh = phigh = 0;

    for(size=1024; size <= sizeof data; size <<= 1) {
        for(i=0; i<sizeof plot; i++) plot[i] = ' ';
        plot[(100*(sizeof plot-2))/100] = '|';
        plot[( 75*(sizeof plot-2))/100] = '|';
        plot[( 50*(sizeof plot-2))/100] = '|';
        plot[( 25*(sizeof plot-2))/100] = '|';
        plot[(  0*(sizeof plot-2))/100] = '|';
        printf("%7d ", size); fflush(stdout);

        printf("%7d ", rval = do_random(seconds, size));
        if(rhigh == 0) rhigh = rval;
        printf("%3d%% ",rval*100/rhigh); fflush(stdout);

        printf("%7d ", sval = do_sequential(seconds, size));
        if(shigh == 0) shigh = sval;
        printf("%3d%% ",sval*100/shigh);

	phigh = rhigh > shigh ? rhigh : shigh;
        plot[(rval*(sizeof plot-2)+phigh/2)/phigh] = '*';
        plot[(sval*(sizeof plot-2)+phigh/2)/phigh] = '@';
        printf("%46.46s\n", plot); fflush(stdout);

        if((size+size/2) <= sizeof data) {
            plot[0] = '|'; for(i=1; i<sizeof plot; i++) plot[i] = ' ';
            printf("%8d ", size+size/2); fflush(stdout);

            printf("%7d ", rval = do_random(seconds, size+size/2));
            printf("%3d%% ",rval*100/rhigh);fflush(stdout);

            printf("%7d ", sval = do_sequential(seconds, size+size/2));
            printf("%3d%% ",sval*100/shigh);

            plot[(rval*(sizeof plot-2)+phigh/2)/phigh] = '*';
            plot[(sval*(sizeof plot-2)+phigh/2)/phigh] = '@';
            printf("%46.46s\n", plot); fflush(stdout);
        }
    }
}



More information about the NCLUG mailing list