Skip to content

Commit

Permalink
initial mem.c and related commit
Browse files Browse the repository at this point in the history
  • Loading branch information
remzi-arpacidusseau committed May 21, 2020
1 parent a38ab45 commit 31c4ccc
Show file tree
Hide file tree
Showing 3 changed files with 170 additions and 0 deletions.
6 changes: 6 additions & 0 deletions vm-beyondphys/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@

all: mem

mem: mem.c
gcc -o mem mem.c -Wall -O

97 changes: 97 additions & 0 deletions vm-beyondphys/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@

# Overview

In this homework, you'll be investigating swap performance with a simple
program found in `mem.c`. The program is really simple: it just allocates an
array of integers of a certain size, and then proceeds to loop through it
(repeatedly), incrementing each value in the array.

Type `make` to build it (and look at the file `Makefile` for details about how
the build works).

Then, type `./mem` followed by a number to run it. The number is the size (in
MB) of the array. Thus, to run with a small array (size 1 MB):

```sh
prompt> ./mem 1
```

and to run with a larger array (size 1 GB):

```sh
prompt> ./mem 1024
```

The program prints out the time it takes to go through each loop as well as
the bandwidth (in MB/s). Bandwidth is particularly interesting to know as it
gives you a sense of how fast the system you're using can move through data;
on modern systems, this is likely in the GB/s range.

Here is what the output looks like for a typical run:

```sh
prompt> ./mem 1000
allocating 1048576000 bytes (1000.00 MB)
number of integers in array: 262144000
loop 0 in 448.11 ms (bandwidth: 2231.61 MB/s)
loop 1 in 345.38 ms (bandwidth: 2895.38 MB/s)
loop 2 in 345.18 ms (bandwidth: 2897.07 MB/s)
loop 3 in 345.23 ms (bandwidth: 2896.61 MB/s)
^C
prompt>
```

The program first tells you how much memory it allocated (in bytes, MB, and in
the number of integers), and then starts looping through the array. The first
loop (in the example above) took 448 milliseconds; because the program
accessed the 1000 MB in just under half a second, the computed bandwidth is
(not surprisingly) just over 2000 MB/s.

The program continues by doing the same thing over and over, for loops 1, 2,
etc.

Important: to stop the program, you must kill it. This task is accomplished on
Linux (and all Unix-based systems) by typing control-C (^C) as shown above.

Note that when you run with small array sizes, each loop's performance numbers
won't be printed. For example:

```sh
prompt> ./mem 1
allocating 1048576 bytes (1.00 MB)
number of integers in array: 262144
loop 0 in 0.71 ms (bandwidth: 1414.61 MB/s)
loop 607 in 0.33 ms (bandwidth: 3039.35 MB/s)
loop 1215 in 0.33 ms (bandwidth: 3030.57 MB/s)
loop 1823 in 0.33 ms (bandwidth: 3039.35 MB/s)
^C
prompt>
```

In this case, the program only prints out a sample of outputs, so as not to
flood the screen with too much output.

The code itself is simple to understand. The first important part is a memory
allocation:

```c
// the big memory allocation happens here
int *x = malloc(size_in_bytes);
```

Then, the main loop begins:

```c
while (1) {
x[i++] += 1; // main work of loop done here.
```
The rest is just timing and printing out information. See `mem.c` for details.
Much of the homework revolves around using the tool vmstat to monitor what is
happening with the system. Read the vmstat man page (type `man vmstat`) for
details on how it works, and what each column of output means.
67 changes: 67 additions & 0 deletions vm-beyondphys/mem.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <sys/time.h>

// Simple routine to return absolute time (in seconds).
double Time_GetSeconds() {
struct timeval t;
int rc = gettimeofday(&t, NULL);
assert(rc == 0);
return (double) ((double)t.tv_sec + (double)t.tv_usec / 1e6);
}

// Program that allocates an array of ints of certain size,
// and then proceeeds to update each int in a loop, forever.
int main(int argc, char *argv[]) {
if (argc != 2) {
fprintf(stderr, "usage: spin <memory (MB)>\n");
exit(1);
}
long long int size = (long long int) atoi(argv[1]);
long long int size_in_bytes = size * 1024 * 1024;

printf("allocating %lld bytes (%.2f MB)\n",
size_in_bytes, size_in_bytes / (1024 * 1024.0));

// the big memory allocation happens here
int *x = malloc(size_in_bytes);
if (x == NULL) {
fprintf(stderr, "memory allocation failed\n");
exit(1);
}

long long int num_ints = size_in_bytes / sizeof(int);
printf(" number of integers in array: %lld\n", num_ints);

// now the main loop: each time through, touch each integer
// (and increment its value by 1).
int i = 0;
double time_since_last_print = 2.0;
double t = Time_GetSeconds();
int loop_count = 0;
while (1) {
x[i++] += 1; // main work of loop done here.

// if we've gone through the whole loop, reset a bunch of stuff
// and then (perhaps) print out some statistics.
if (i == num_ints) {
double delta_time = Time_GetSeconds() - t;
time_since_last_print += delta_time;
if (time_since_last_print >= 0.2) { // only print every .2 seconds
printf("loop %d in %.2f ms (bandwidth: %.2f MB/s)\n",
loop_count, 1000 * delta_time,
size_in_bytes / (1024.0*1024.0*delta_time));
time_since_last_print = 0;
}

i = 0;
t = Time_GetSeconds();
loop_count++;
}
}

return 0;
}

0 comments on commit 31c4ccc

Please sign in to comment.