Commit 2e07d771 authored by Kirill Smelkov's avatar Kirill Smelkov

.

parents
/t_syspread_c
/t_syspread_go
/t_copy_c
/t_copy_go
all : t_syspread_c t_syspread_go t_copy_c t_copy_go
CFLAGS = -g -O2 -Wall
XDAT = /dev/shm/x.dat
$(XDAT) :
dd if=/dev/urandom of=$(XDAT) bs=4K count=1
bench : bench_c bench_go
bench_c : t_syspread_c $(XDAT) t_copy_c
./t_syspread_c $(XDAT) >t_syspread_c.csv
./t_copy_c >t_copy_c.csv
bench_go : t_syspread_go $(XDAT) t_copy_go
./t_syspread_go $(XDAT) >t_syspread_go.csv
./t_copy_go >t_copy_go.csv
t_syspread_go: t_syspread_go.go
go build $<
t_copy_go: t_copy_go.go
go build $<
File added
#!/usr/bin/env python
import matplotlib.pyplot as plt
import csv
import numpy as np
# loadxy loads (x int; y float) vectors from a csv file
def loadxy(path):
x = []
y = []
with open(path, 'r') as f:
csvf = csv.reader(f, delimiter='\t')
for row in csvf:
x.append(int(row[0]))
y.append(float(row[1]))
return x, y
def plotxy(xy, **kw):
x, y = xy
plt.plot(x, y, **kw)
pread_c = loadxy("t_syspread_c.csv")
pread_go = loadxy("t_syspread_go.csv")
copy_c = loadxy("t_copy_c.csv")
copy_go = loadxy("t_copy_go.csv")
plt.title("Timing for syspread & memcopy")
plotxy(pread_c, label="syspread/c")
plotxy(pread_go, label="syspread/go")
plotxy(copy_c, label="copy/c")
plotxy(copy_go, label="copy/go")
assert pread_c[0] == copy_c[0]
plotxy((pread_c[0], np.array(pread_c[1]) - np.array(copy_c[1])), label="syspread/c - copy/c")
plt.legend()
plt.ylabel('time (ns)')
plt.xlabel('buffer size (bytes)')
#plt.show()
plt.savefig('syspread.png')
This diff is collapsed.
Tsyspread/c 0..4K
Tsyspread/go 0..4K
Tcopy 0..4K
C(copy) = ~ 0.01ns / byte <- β (= ~ 40ns for 4K)
C(syscall/c) = ~ 175ns <- α
C(syscall/go) = ~ 325ns <- α
C(sysread(n)) = α + β⋅n
C(copy(n)) = β⋅n
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <string.h>
// microtime returns current time as double
double microtime() {
int err;
struct timeval tv;
err = gettimeofday(&tv, NULL);
if (err == -1) {
perror("gettimeofday");
abort();
}
return tv.tv_sec + 1E-6 * tv.tv_usec;
}
// 12345678
#define NITER 1000000
#define BUFSIZE 4096
static char buf[BUFSIZE];
static char buf2[BUFSIZE];
int main() {
int i;
size_t size;
for (size = 0; size <= BUFSIZE;) {
// warmup
memcpy(buf2, buf, size);
double Tstart, Tend;
Tstart = microtime();
for (i = 0; i < NITER; i++) {
memcpy(buf2, buf, size);
}
Tend = microtime();
printf("%ld\t%.1f\n", size, (Tend - Tstart) / NITER / 1E-9);
if (size < 16) {
size += 1; // detailed start
} else if (size < 128) {
size += 16;
} else {
size += 128;
}
}
}
0 2.8
1 2.4
2 2.7
3 2.7
4 3.0
5 2.9
6 3.0
7 3.0
8 2.4
9 2.5
10 2.5
11 2.5
12 2.6
13 2.6
14 2.5
15 2.5
16 2.4
32 2.5
48 2.5
64 2.1
80 4.3
96 2.7
112 3.5
128 4.6
256 3.5
384 5.3
512 6.8
640 7.6
768 8.7
896 10.0
1024 11.2
1152 12.1
1280 13.0
1408 14.2
1536 15.4
1664 16.7
1792 17.8
1920 18.9
2048 20.1
2176 22.4
2304 24.2
2432 25.8
2560 26.6
2688 27.6
2816 28.4
2944 29.6
3072 30.9
3200 32.1
3328 33.4
3456 34.4
3584 35.9
3712 36.6
3840 38.1
3968 38.9
4096 41.0
0 2.0
1 3.8
2 3.1
3 3.2
4 2.4
5 3.5
6 3.5
7 3.5
8 2.4
9 3.5
10 3.5
11 3.5
12 3.5
13 3.5
14 3.4
15 3.4
16 2.9
32 3.0
48 4.5
64 4.0
80 6.6
96 6.6
112 7.1
128 6.9
256 10.4
384 10.8
512 12.2
640 13.2
768 14.5
896 15.7
1024 16.8
1152 18.3
1280 19.3
1408 20.5
1536 21.4
1664 22.8
1792 24.1
1920 25.1
2048 26.0
2176 27.5
2304 28.9
2432 29.6
2560 31.3
2688 32.7
2816 33.5
2944 34.6
3072 35.5
3200 37.0
3328 38.2
3456 39.2
3584 40.8
3712 41.8
3840 43.0
3968 44.0
4096 45.3
package main
import (
"fmt"
"time"
)
// 12345678
const Niter = 1000000
const BufSize = 4096
var buf [BufSize]byte
var buf2 [BufSize]byte
func main() {
for size := 0; size <= BufSize; {
src := buf[:size]
dst := buf2[:size]
// warmup
copy(dst, src)
Tstart := time.Now()
for i := 0; i < Niter; i++ {
copy(dst, src)
}
Tend := time.Now()
fmt.Printf("%v\t%.1f\n", size, float64(Tend.Sub(Tstart).Nanoseconds()) / Niter)
switch {
case size < 16:
size += 1 // detailed start
case size < 128:
size += 16
default:
size += 128
}
}
}
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
// 12345678
#define NITER 1000000
// microtime returns current time as double
double microtime() {
int err;
struct timeval tv;
err = gettimeofday(&tv, NULL);
if (err == -1) {
perror("gettimeofday");
abort();
}
return tv.tv_sec + 1E-6 * tv.tv_usec;
}
#define BUFSIZE 4096
static char buf[BUFSIZE];
// xpread is pread(2) but aborts on an error or when fewer bytes was read
void xpread(int fd, void *buf, size_t count, off_t offset) {
ssize_t n;
n = pread(fd, buf, count, offset);
if (n == -1) {
perror("pread");
abort();
}
if (n != count) {
fprintf(stderr, "pread(%ld) -> %ld\n", count, n);
abort();
}
}
int main(int argc, char *argv[]) {
int fd, i;
size_t size;
if (argc < 2) {
fprintf(stderr, "Usage: %s <file>\n", argv[0]);
exit(1);
}
fd = open(argv[1], O_RDONLY);
if (fd == -1) {
perror("open");
abort();
}
for (size = 0; size <= BUFSIZE;) {
// warmup
xpread(fd, &buf, size, /*offset=*/0);
double Tstart, Tend;
Tstart = microtime();
for (i = 0; i < NITER; i++) {
xpread(fd, buf, size, /*offset=*/0);
}
Tend = microtime();
printf("%ld\t%.1f\n", size, (Tend - Tstart) / NITER / 1E-9);
if (size < 16) {
size += 1; // detailed start
} else if (size < 128) {
size += 16;
} else {
size += 128;
}
}
}
0 159.5
1 186.2
2 178.3
3 177.6
4 178.9
5 177.2
6 177.3
7 177.9
8 178.0
9 177.8
10 177.7
11 177.3
12 177.4
13 178.4
14 177.2
15 178.0
16 177.3
32 177.2
48 177.5
64 177.6
80 177.9
96 180.1
112 180.8
128 179.9
256 184.0
384 186.2
512 187.2
640 188.2
768 189.4
896 191.0
1024 192.4
1152 193.9
1280 195.0
1408 195.6
1536 197.9
1664 198.9
1792 199.4
1920 201.0
2048 201.6
2176 203.8
2304 204.5
2432 205.8
2560 207.1
2688 207.5
2816 210.1
2944 210.0
3072 214.4
3200 215.2
3328 216.3
3456 220.7
3584 219.0
3712 222.0
3840 221.2
3968 222.8
4096 224.3
0 14.4
1 335.7
2 325.8
3 325.2
4 325.8
5 325.7
6 325.3
7 325.4
8 326.7
9 325.7
10 325.3
11 326.4
12 325.7
13 325.8
14 328.9
15 325.5
16 326.4
32 325.9
48 325.4
64 325.8
80 326.5
96 328.5
112 329.4
128 328.6
256 329.4
384 330.4
512 332.3
640 333.9
768 334.0
896 335.8
1024 336.9
1152 338.6
1280 339.5
1408 340.6
1536 342.0
1664 342.8
1792 343.7
1920 345.7
2048 347.2
2176 347.2
2304 348.3
2432 350.2
2560 351.2
2688 352.3
2816 354.0
2944 355.0
3072 358.9
3200 360.2
3328 361.3
3456 362.0
3584 363.7
3712 365.0
3840 366.4
3968 367.0
4096 368.0
package main
import (
"flag"
"fmt"
"log"
"os"
"runtime/pprof"
"time"
)
// 12345678
const Niter = 1000000
// xpread is pread(2) but aborts on an error or when fewer bytes was read
func xpread(f *os.File, buf []byte, offset int64) {
n, err := f.ReadAt(buf, offset)
if err != nil {
panic(err)
}
if n != len(buf) {
panic(fmt.Errorf("pread(%v) -> %v", len(buf), n))
}
}
const BufSize = 4096
var buf [BufSize]byte
var cpuprofile = flag.String("cpuprofile", "", "write cpu profile `file`")
func main() {
flag.Parse()
if len(flag.Args()) < 1 {
log.Fatalf("Usage: %s <file>", os.Args[0])
}
if *cpuprofile != "" {
f, err := os.Create(*cpuprofile)
if err != nil {
log.Fatal("could not create CPU profile: ", err)
}
if err := pprof.StartCPUProfile(f); err != nil {
log.Fatal("could not start CPU profile: ", err)
}
defer pprof.StopCPUProfile()
}
f, err := os.Open(flag.Args()[0])
if err != nil {
log.Fatal(err)
}
for size := 0; size <= BufSize; {
sbuf := buf[:size]
// warmup
xpread(f, sbuf, /*offset=*/0)
Tstart := time.Now()
for i := 0; i < Niter; i++ {
xpread(f, sbuf, /*offset=*/0)
}
Tend := time.Now()
fmt.Printf("%v\t%.1f\n", size, float64(Tend.Sub(Tstart).Nanoseconds()) / Niter)
switch {
case size < 16:
size += 1 // detailed start
case size < 128:
size += 16
default:
size += 128
}
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment