Created
February 2, 2018 05:40
-
-
Save jimblandy/f1508e8c27b9aa3c32185ac0104c05b9 to your computer and use it in GitHub Desktop.
Dumb benchmark of memory initialization and file writing speeds
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <assert.h> | |
#include <errno.h> | |
#include <fcntl.h> | |
#include <math.h> | |
#include <stdlib.h> | |
#include <stdint.h> | |
#include <stdio.h> | |
#include <string.h> | |
#include <sys/stat.h> | |
#include <sys/types.h> | |
#include <time.h> | |
#include <unistd.h> | |
#include <functional> | |
#include <iostream> | |
using std::cout; | |
int check_syscall(const char* operation, int result) { | |
if (result < 0) { | |
fprintf(stderr, "%s failed: %s", operation, strerror(errno)); | |
exit(1); | |
} | |
return result; | |
} | |
struct Seconds { | |
double s; | |
Seconds(double s) : s(s) { } | |
Seconds(const struct timespec &time) | |
: s(time.tv_sec + (double) time.tv_nsec / 1e9) | |
{ } | |
Seconds operator-(const Seconds& rhs) const { | |
return Seconds(this->s - rhs.s); | |
} | |
Seconds operator/(double d) const { | |
return Seconds(this->s / d); | |
} | |
}; | |
std::ostream& operator<<(std::ostream& stream, const Seconds& time) | |
{ | |
double sec = time.s; | |
if (sec >= 1 || sec == 0) | |
stream << sec << "s"; | |
else if (sec >= 1e-3) | |
stream << (sec * 1e3) << "ms"; | |
else if (sec >= 1e-6) | |
stream << (sec * 1e6) << "µs"; | |
else | |
stream << (sec * 1e9) << "ns"; | |
return stream; | |
} | |
struct PerUnit { | |
double count; | |
const char* unit; | |
Seconds time; | |
PerUnit(double count, const char* unit, const Seconds& time) | |
: count(count), unit(unit), time(time) | |
{ } | |
}; | |
std::ostream& operator<<(std::ostream& stream, const PerUnit& per) | |
{ | |
stream << (per.time / per.count) << " per " << per.unit; | |
} | |
template<typename F> | |
Seconds measure(F f) { | |
struct timespec start, end; | |
check_syscall("get start time", clock_gettime(CLOCK_REALTIME, &start)); | |
f(); | |
check_syscall("get end time", clock_gettime(CLOCK_REALTIME, &end)); | |
return Seconds(end) - Seconds(start); | |
} | |
int main(int argc, char** argv) { | |
size_t size = 1024 * 1024 * 1024; | |
//size_t size = 1024 * 1024; | |
uint8_t* buf; | |
cout << "allocate buffer: " | |
<< measure([&]() { buf = static_cast<uint8_t*>(malloc(size)); }) | |
<< '\n'; | |
cout << "initialize buffer, first pass: " | |
<< PerUnit(size, "byte", | |
measure([&]() { | |
for (size_t i = 0; i < size; i++) | |
buf[i] = i & 0xff; | |
})) | |
<< '\n'; | |
cout << "initialize buffer, second pass: " | |
<< PerUnit(size, "byte", | |
measure([&]() { | |
for (size_t i = 0; i < size; i++) | |
buf[i] = i & 0xff; | |
})) | |
<< '\n'; | |
cout << "initialize buffer, third pass: " | |
<< PerUnit(size, "byte", | |
measure([&]() { | |
for (size_t i = 0; i < size; i++) | |
buf[i] = i & 0xff; | |
})) | |
<< '\n'; | |
int fd; | |
cout << "open and truncate output file: " | |
<< measure([&]() { | |
fd = check_syscall("open output file", | |
open("write.cc-output", O_WRONLY|O_CREAT|O_TRUNC, 0666)); | |
}) | |
<< '\n'; | |
cout << "write data to file, first pass: " | |
<< PerUnit(size, "byte", | |
measure([&]() { | |
check_syscall("write data to file", write(fd, buf, size)); | |
})) | |
<< '\n'; | |
cout << "write data to file, second pass: " | |
<< PerUnit(size, "byte", | |
measure([&]() { | |
check_syscall("write data to file", write(fd, buf, size)); | |
})) | |
<< '\n'; | |
cout << "write data to file, third pass: " | |
<< PerUnit(size, "byte", | |
measure([&]() { | |
check_syscall("write data to file", write(fd, buf, size)); | |
})) | |
<< '\n'; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment