1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
|
#include <fcntl.h>
#include <port/unistd.h>
#include <stdlib.h>
#include <time.h>
#include <stdlib.h>
#if !defined(__APPLE__) && !defined(__FreeBSD__)
#include <malloc.h>
#endif
#include <poll.h>
#include <iostream>
#include <iomanip>
#include <vector>
#include <random>
#include <pcg_random.hpp>
#include <IO/ReadHelpers.h>
#include <Poco/Exception.h>
#include <Common/Exception.h>
#include <Common/randomSeed.h>
#include <common/ThreadPool.h>
#include <Common/Stopwatch.h>
#include <port/clock.h>
namespace DB
{
namespace ErrorCodes
{
extern const int CANNOT_OPEN_FILE;
extern const int CANNOT_CLOSE_FILE;
extern const int CANNOT_READ_FROM_FILE_DESCRIPTOR;
extern const int CANNOT_WRITE_TO_FILE_DESCRIPTOR;
extern const int CANNOT_FSYNC;
extern const int SYSTEM_ERROR;
}
}
enum Mode
{
MODE_READ,
MODE_WRITE,
};
int mainImpl(int argc, char ** argv)
{
using namespace DB;
const char * file_name = 0;
Mode mode = MODE_READ;
UInt64 min_offset = 0;
UInt64 max_offset = 0;
UInt64 block_size = 0;
UInt64 descriptors = 0;
UInt64 count = 0;
if (argc != 8)
{
std::cerr << "Usage: " << argv[0] << " file_name r|w min_offset max_offset block_size descriptors count" << std::endl;
return 1;
}
file_name = argv[1];
min_offset = parse<UInt64>(argv[3]);
max_offset = parse<UInt64>(argv[4]);
block_size = parse<UInt64>(argv[5]);
descriptors = parse<UInt64>(argv[6]);
count = parse<UInt64>(argv[7]);
if (!strcmp(argv[2], "r"))
mode = MODE_READ;
else if (!strcmp(argv[2], "w"))
mode = MODE_WRITE;
else
throw Poco::Exception("Invalid mode");
std::vector<int> fds(descriptors);
for (size_t i = 0; i < descriptors; ++i)
{
fds[i] = open(file_name, O_SYNC | ((mode == MODE_READ) ? O_RDONLY : O_WRONLY));
if (-1 == fds[i])
throwFromErrno("Cannot open file", ErrorCodes::CANNOT_OPEN_FILE);
}
std::vector<char> buf(block_size);
pcg64 rng(randomSeed());
Stopwatch watch;
std::vector<pollfd> polls(descriptors);
for (size_t i = 0; i < descriptors; ++i)
{
polls[i].fd = fds[i];
polls[i].events = (mode == MODE_READ) ? POLLIN : POLLOUT;
polls[i].revents = 0;
}
size_t ops = 0;
while (ops < count)
{
if (poll(&polls[0], descriptors, -1) <= 0)
throwFromErrno("poll failed", ErrorCodes::SYSTEM_ERROR);
for (size_t i = 0; i < descriptors; ++i)
{
if (!polls[i].revents)
continue;
if (polls[i].revents != polls[i].events)
throw Poco::Exception("revents indicates error");
polls[i].revents = 0;
++ops;
long rand_result1 = rng();
long rand_result2 = rng();
long rand_result3 = rng();
size_t rand_result = rand_result1 ^ (rand_result2 << 22) ^ (rand_result3 << 43);
size_t offset;
offset = min_offset + rand_result % ((max_offset - min_offset) / block_size) * block_size;
if (mode == MODE_READ)
{
if (static_cast<int>(block_size) != pread(fds[i], &buf[0], block_size, offset))
throwFromErrno("Cannot read", ErrorCodes::CANNOT_READ_FROM_FILE_DESCRIPTOR);
}
else
{
if (static_cast<int>(block_size) != pwrite(fds[i], &buf[0], block_size, offset))
throwFromErrno("Cannot write", ErrorCodes::CANNOT_WRITE_TO_FILE_DESCRIPTOR);
}
}
}
for (size_t i = 0; i < descriptors; ++i)
{
if (fsync(fds[i]))
throwFromErrno("Cannot fsync", ErrorCodes::CANNOT_FSYNC);
}
watch.stop();
for (size_t i = 0; i < descriptors; ++i)
{
if (0 != close(fds[i]))
throwFromErrno("Cannot close file", ErrorCodes::CANNOT_CLOSE_FILE);
}
std::cout << std::fixed << std::setprecision(2)
<< "Done " << count << " ops" << " in " << watch.elapsedSeconds() << " sec."
<< ", " << count / watch.elapsedSeconds() << " ops/sec."
<< ", " << count * block_size / watch.elapsedSeconds() / 1000000 << " MB/sec."
<< std::endl;
return 0;
}
int main(int argc, char ** argv)
{
try
{
return mainImpl(argc, argv);
}
catch (const Poco::Exception & e)
{
std::cerr << e.what() << ", " << e.message() << std::endl;
return 1;
}
}
|