Skip to content

Instantly share code, notes, and snippets.

@jimblandy
Created February 2, 2018 05:40
Show Gist options
  • Save jimblandy/f1508e8c27b9aa3c32185ac0104c05b9 to your computer and use it in GitHub Desktop.
Save jimblandy/f1508e8c27b9aa3c32185ac0104c05b9 to your computer and use it in GitHub Desktop.
Dumb benchmark of memory initialization and file writing speeds
#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