Last active
August 29, 2015 14:22
-
-
Save Lazin/0cb54feefa1c5c17ecf7 to your computer and use it in GitHub Desktop.
This file contains 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 <iostream> | |
#include <cstdio> | |
#include <stdexcept> | |
#include <unistd.h> | |
#include <thread> | |
#include <vector> | |
#include <cstring> | |
#include <time.h> | |
class PerfTimer | |
{ | |
public: | |
PerfTimer(); | |
void restart(); | |
double elapsed() const; | |
private: | |
timespec _start_time; | |
}; | |
PerfTimer::PerfTimer() { | |
clock_gettime(CLOCK_MONOTONIC_RAW, &_start_time); | |
} | |
void PerfTimer::restart() { | |
clock_gettime(CLOCK_MONOTONIC_RAW, &_start_time); | |
} | |
double PerfTimer::elapsed() const { | |
timespec curr; | |
clock_gettime(CLOCK_MONOTONIC_RAW, &curr); | |
return double(curr.tv_sec - _start_time.tv_sec) + | |
double(curr.tv_nsec - _start_time.tv_nsec)/1000000000.0; | |
} | |
const char* PATH = "/tmp/perftest.tmp"; | |
const size_t FSIZE = 10/*GB*/*1024*1024*1024l; | |
const int NREGIONS = 4; | |
FILE* create_file() { | |
auto res = fopen(PATH, "w"); | |
if (res == nullptr) { | |
throw std::runtime_error("can't open file"); | |
} | |
return res; | |
} | |
void truncate(FILE* file) { | |
int fd = fileno(file); | |
if (ftruncate(fd, FSIZE)) { | |
throw std::runtime_error("can't truncate file"); | |
} | |
} | |
void close(FILE* file) { | |
if (fclose(file) != 0) { | |
throw std::runtime_error("can't close file"); | |
} | |
} | |
int main() { | |
std::cout << "Creating " << PATH << " file" << std::endl; | |
try { | |
FILE* file = create_file(); | |
truncate(file); | |
std::vector<std::thread> threads; | |
PerfTimer total; | |
for (int jobix = NREGIONS; jobix-->0;) { | |
threads.emplace_back([jobix]() { | |
try { | |
FILE* file = create_file(); | |
PerfTimer jobtm; | |
int fd = fileno(file); | |
const size_t BUFSIZE = 0x1000; | |
std::vector<char> buffer; | |
buffer.resize(BUFSIZE); | |
for (int i = 0; i < BUFSIZE; i++) { | |
buffer[i] = 32 + rand()%10; | |
} | |
const size_t BLOCKSIZE = FSIZE/NREGIONS; | |
const size_t INITIAL_OFF = jobix*BUFSIZE; | |
const size_t LAST_OFF = FSIZE; | |
for (size_t offset = INITIAL_OFF; offset < LAST_OFF; offset += BUFSIZE*NREGIONS) { | |
fseek(file, offset, SEEK_SET); | |
if (write(fd, buffer.data(), BUFSIZE) < 0) { | |
throw std::runtime_error("can't write data to file"); | |
} | |
} | |
fflush(file); | |
close(file); | |
std::cout << "job " << jobix << " done in " << jobtm.elapsed() << " seconds " << "\n"; | |
} catch (const std::exception& e) { | |
std::cout << "error in job " << jobix << ": " << e.what() << std::endl; | |
} | |
}); | |
} | |
for (int jobix = NREGIONS; jobix-->0;) { | |
threads.at(jobix).join(); | |
} | |
close(file); | |
std::cout << "done in " << total.elapsed() << " seconds" << std::endl; | |
} catch (const std::exception& e) { | |
std::cout << "error main " << e.what() << std::endl; | |
} | |
return 0; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment