#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
const size_t KB=1024, MB=1024*1024, GB=1024*1024*1024;
class Test {
void test(size_t size) {
init_timer();
this->size=size;
action(&Test::alloc_data,0,"allocate %.2fGb",(double)size/GB);
action(&Test::seq,size,"init sequential");
action(&Test::run,size,"test sequential ram read");
action(&Test::shuffle,size,"shuffle");
action(&Test::run,size,"test random ram read");
free_data();
}
void seq() {
size_t i,n=get_n();
for(i=0;i<n-1;i++) data[i]=&data[i+1];
data[n-1]=&data[0];
}
void shuffle() {
size_t n=get_n();
for(size_t i=1;i<n;i++) {
size_t j=i+rnd(n-i);
void* t=data[i];data[i]=data[j];data[j]=t;
}
}
void run() {
size_t n=get_n();
void* p=data[0];
for(size_t i=0;i<n;i++) p=*(void**)p;
dummy=p;
}
size_t get_n() { return size/sizeof(void**); }
void alloc_data() { data=(void**)malloc(size); }
void free_data() { free((void*)data); data=0; }
void init_timer() {
if (clock_gettime(CLOCK_REALTIME,t0)) {
fprintf(stderr,"FATAL_ERROR: no realtime clock\n");
}
}
double timer() {
struct timespec ts[1];
clock_gettime(CLOCK_REALTIME,ts);
ts->tv_sec-=t0->tv_sec;
if (ts->tv_nsec<t0->tv_nsec) {
ts->tv_sec--;
ts->tv_nsec=1000000000-t0->tv_nsec+ts->tv_nsec;
} else {
ts->tv_nsec-=t0->tv_nsec;
}
return ts->tv_sec+1e-9*ts->tv_nsec;
}
static size_t rnd(size_t n) {
int s=15; size_t m=0x7FFF;
size_t x=rand()&0x7FFF; m<<=15;
while(m) {
x|=((size_t)(rand()&0x7FFF))<<s;
m<<=15;s+=15;
}
return x%n;
}
void action(void (Test::*fn)(),size_t size,const char *fmt,...) {
va_list v; va_start(v,fmt);
double t1,t2,rate,dt;
vprintf(fmt,v);
t1=timer();
(this->*fn)();
t2=timer();
dt=t2-t1;
if (size!=0) {
rate=dt>0 ? size/dt : 0;
printf(" dt=%.2fms rate=%.1fMb/s\n",dt*1e3,rate/MB);
} else {
printf(" dt=%.2fus\n",dt*1e6);
}
}
void** data; size_t size;
struct timespec t0[1];
volatile void* dummy;
public:
Test(size_t size) { test(size); }
};
int main(int argc, char const *argv[]) {
Test(128*MB);
return 0;
}
I2luY2x1ZGUgPHRpbWUuaD4KI2luY2x1ZGUgPHN0ZGlvLmg+CiNpbmNsdWRlIDxzdGRsaWIuaD4KI2luY2x1ZGUgPHN0cmluZy5oPgojaW5jbHVkZSA8c3RkYXJnLmg+Cgpjb25zdCBzaXplX3QgS0I9MTAyNCwgTUI9MTAyNCoxMDI0LCBHQj0xMDI0KjEwMjQqMTAyNDsKCmNsYXNzIFRlc3QgewogICAgdm9pZCB0ZXN0KHNpemVfdCBzaXplKSB7CiAgICAgICAgaW5pdF90aW1lcigpOwogICAgICAgIHRoaXMtPnNpemU9c2l6ZTsKICAgICAgICBhY3Rpb24oJlRlc3Q6OmFsbG9jX2RhdGEsMCwiYWxsb2NhdGUgJS4yZkdiIiwoZG91YmxlKXNpemUvR0IpOwogICAgICAgIGFjdGlvbigmVGVzdDo6c2VxLHNpemUsImluaXQgc2VxdWVudGlhbCIpOwogICAgICAgIGFjdGlvbigmVGVzdDo6cnVuLHNpemUsInRlc3Qgc2VxdWVudGlhbCByYW0gcmVhZCIpOwogICAgICAgIGFjdGlvbigmVGVzdDo6c2h1ZmZsZSxzaXplLCJzaHVmZmxlIik7CiAgICAgICAgYWN0aW9uKCZUZXN0OjpydW4sc2l6ZSwidGVzdCByYW5kb20gcmFtIHJlYWQiKTsKICAgICAgICBmcmVlX2RhdGEoKTsKICAgIH0KICAgIHZvaWQgc2VxKCkgewogICAgICAgIHNpemVfdCBpLG49Z2V0X24oKTsKICAgICAgICBmb3IoaT0wO2k8bi0xO2krKykgZGF0YVtpXT0mZGF0YVtpKzFdOwogICAgICAgIGRhdGFbbi0xXT0mZGF0YVswXTsKICAgIH0KICAgIHZvaWQgc2h1ZmZsZSgpIHsKICAgICAgICBzaXplX3Qgbj1nZXRfbigpOwogICAgICAgIGZvcihzaXplX3QgaT0xO2k8bjtpKyspIHsKICAgICAgICAgICAgc2l6ZV90IGo9aStybmQobi1pKTsKICAgICAgICAgICAgdm9pZCogdD1kYXRhW2ldO2RhdGFbaV09ZGF0YVtqXTtkYXRhW2pdPXQ7CiAgICAgICAgfQogICAgfQogICAgdm9pZCBydW4oKSB7CiAgICAgICAgc2l6ZV90IG49Z2V0X24oKTsKICAgICAgICB2b2lkKiBwPWRhdGFbMF07CiAgICAgICAgZm9yKHNpemVfdCBpPTA7aTxuO2krKykgcD0qKHZvaWQqKilwOwogICAgICAgIGR1bW15PXA7CiAgICB9CiAgICBzaXplX3QgZ2V0X24oKSB7IHJldHVybiBzaXplL3NpemVvZih2b2lkKiopOyB9CiAgICB2b2lkIGFsbG9jX2RhdGEoKSB7IGRhdGE9KHZvaWQqKiltYWxsb2Moc2l6ZSk7IH0KICAgIHZvaWQgZnJlZV9kYXRhKCkgeyBmcmVlKCh2b2lkKilkYXRhKTsgZGF0YT0wOyB9CiAgICB2b2lkIGluaXRfdGltZXIoKSB7CiAgICAgICAgaWYgKGNsb2NrX2dldHRpbWUoQ0xPQ0tfUkVBTFRJTUUsdDApKSB7CiAgICAgICAgICAgIGZwcmludGYoc3RkZXJyLCJGQVRBTF9FUlJPUjogbm8gcmVhbHRpbWUgY2xvY2tcbiIpOwogICAgICAgIH0KICAgIH0KICAgIGRvdWJsZSB0aW1lcigpIHsKICAgICAgICBzdHJ1Y3QgdGltZXNwZWMgdHNbMV07CiAgICAgICAgY2xvY2tfZ2V0dGltZShDTE9DS19SRUFMVElNRSx0cyk7CiAgICAgICAgdHMtPnR2X3NlYy09dDAtPnR2X3NlYzsKICAgICAgICBpZiAodHMtPnR2X25zZWM8dDAtPnR2X25zZWMpIHsKICAgICAgICAgICAgICAgIHRzLT50dl9zZWMtLTsKICAgICAgICAgICAgICAgIHRzLT50dl9uc2VjPTEwMDAwMDAwMDAtdDAtPnR2X25zZWMrdHMtPnR2X25zZWM7CiAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIHRzLT50dl9uc2VjLT10MC0+dHZfbnNlYzsKICAgICAgICB9CiAgICAgICAgcmV0dXJuIHRzLT50dl9zZWMrMWUtOSp0cy0+dHZfbnNlYzsKICAgIH0KICAgIHN0YXRpYyBzaXplX3Qgcm5kKHNpemVfdCBuKSB7CiAgICAgICAgaW50IHM9MTU7IHNpemVfdCBtPTB4N0ZGRjsKICAgICAgICBzaXplX3QgeD1yYW5kKCkmMHg3RkZGOyBtPDw9MTU7CiAgICAgICAgd2hpbGUobSkgewogICAgICAgICAgICB4fD0oKHNpemVfdCkocmFuZCgpJjB4N0ZGRikpPDxzOwogICAgICAgICAgICBtPDw9MTU7cys9MTU7CiAgICAgICAgfQogICAgICAgIHJldHVybiB4JW47CiAgICB9CiAgICB2b2lkIGFjdGlvbih2b2lkIChUZXN0OjoqZm4pKCksc2l6ZV90IHNpemUsY29uc3QgY2hhciAqZm10LC4uLikgewogICAgICAgIHZhX2xpc3QgdjsgdmFfc3RhcnQodixmbXQpOwogICAgICAgIGRvdWJsZSB0MSx0MixyYXRlLGR0OwogICAgICAgIHZwcmludGYoZm10LHYpOwogICAgICAgIHQxPXRpbWVyKCk7CiAgICAgICAgKHRoaXMtPipmbikoKTsKICAgICAgICB0Mj10aW1lcigpOwogICAgICAgIGR0PXQyLXQxOwogICAgICAgIGlmIChzaXplIT0wKSB7ICAgICAgICAKICAgICAgICAgICAgcmF0ZT1kdD4wID8gc2l6ZS9kdCA6IDA7CiAgICAgICAgICAgIHByaW50ZigiIGR0PSUuMmZtcyByYXRlPSUuMWZNYi9zXG4iLGR0KjFlMyxyYXRlL01CKTsKICAgICAgICB9IGVsc2UgewogICAgICAgICAgICBwcmludGYoIiBkdD0lLjJmdXNcbiIsZHQqMWU2KTsKICAgICAgICB9CiAgICB9CiAgICB2b2lkKiogZGF0YTsgc2l6ZV90IHNpemU7CiAgICBzdHJ1Y3QgdGltZXNwZWMgdDBbMV07CiAgICB2b2xhdGlsZSB2b2lkKiBkdW1teTsKcHVibGljOgogICAgVGVzdChzaXplX3Qgc2l6ZSkgeyB0ZXN0KHNpemUpOyB9Cn07CgppbnQgbWFpbihpbnQgYXJnYywgY2hhciBjb25zdCAqYXJndltdKSB7CiAgICBUZXN0KDEyOCpNQik7CiAgICByZXR1cm4gMDsKfQo=