148 lines
4.3 KiB
C++
148 lines
4.3 KiB
C++
#include <ConflictSet.h>
|
|
|
|
#include <cerrno>
|
|
#include <chrono>
|
|
#include <cstdio>
|
|
#include <cstring>
|
|
#include <fcntl.h>
|
|
#include <span>
|
|
#include <sys/mman.h>
|
|
#include <sys/stat.h>
|
|
#include <unistd.h>
|
|
#include <vector>
|
|
|
|
using namespace weaselab;
|
|
|
|
double now() {
|
|
return std::chrono::duration_cast<std::chrono::nanoseconds>(
|
|
std::chrono::steady_clock::now().time_since_epoch())
|
|
.count() *
|
|
1e-9;
|
|
}
|
|
|
|
inline size_t getPageSize() {
|
|
static size_t kPageSize = sysconf(_SC_PAGESIZE);
|
|
return kPageSize;
|
|
}
|
|
|
|
/// Helper for rounding up to page size (or some other alignment)
|
|
constexpr inline size_t rightAlign(size_t offset, size_t alignment) {
|
|
return offset % alignment == 0 ? offset
|
|
: ((offset / alignment) + 1) * alignment;
|
|
}
|
|
|
|
int main(int argc, const char **argv) {
|
|
// Use with this dataset https://snap.stanford.edu/data/memetracker9.html
|
|
// Preprocess the files with `sed -i'' '/^Q/d'`
|
|
|
|
double checkTime = 0;
|
|
double addTime = 0;
|
|
double gcTime = 0;
|
|
double checkBytes = 0;
|
|
double addBytes = 0;
|
|
|
|
ConflictSet cs{0};
|
|
int64_t version = 0;
|
|
double timer = 0;
|
|
|
|
int64_t peakMemory = 0;
|
|
|
|
for (int i = 1; i < argc; ++i) {
|
|
int fd = open(argv[i], O_RDONLY);
|
|
struct stat st;
|
|
if (fstat(fd, &st) == -1) {
|
|
int err = errno;
|
|
fprintf(stderr, "stat error %s - %s\n", argv[i], strerror(err));
|
|
fflush(stderr);
|
|
abort();
|
|
}
|
|
|
|
int64_t size = rightAlign(st.st_size, getPageSize());
|
|
const uint8_t *begin =
|
|
(uint8_t *)mmap(0, size, PROT_READ, MAP_PRIVATE, fd, 0);
|
|
madvise((void *)begin, size, MADV_SEQUENTIAL);
|
|
auto *const mapOriginal = begin;
|
|
const auto sizeOriginal = size;
|
|
|
|
using StringView = std::span<const uint8_t>;
|
|
|
|
StringView write;
|
|
std::vector<StringView> reads;
|
|
std::vector<ConflictSet::ReadRange> readRanges;
|
|
std::vector<ConflictSet::Result> results;
|
|
|
|
for (uint8_t *end = (uint8_t *)memchr(begin, '\n', size); end != nullptr;) {
|
|
StringView line{begin, static_cast<size_t>(end - begin)};
|
|
size -= end - begin + 1;
|
|
begin = end + 1;
|
|
end = (uint8_t *)memchr(begin, '\n', size);
|
|
|
|
if (line.size() > 0 && line[0] == 'P') {
|
|
write = line.subspan(2, line.size());
|
|
} else if (line.size() > 0 && line[0] == 'L') {
|
|
reads.push_back(line.subspan(2, line.size()));
|
|
} else if (line.empty()) {
|
|
{
|
|
readRanges.resize(reads.size());
|
|
auto iter = readRanges.begin();
|
|
for (const auto &read : reads) {
|
|
iter->begin.p = (const uint8_t *)read.data();
|
|
iter->begin.len = read.size();
|
|
checkBytes += read.size();
|
|
iter->end.len = 0;
|
|
iter->readVersion = version - 100;
|
|
++iter;
|
|
}
|
|
}
|
|
results.resize(readRanges.size());
|
|
|
|
timer = now();
|
|
cs.check(readRanges.data(), results.data(), readRanges.size());
|
|
checkTime += now() - timer;
|
|
|
|
// Add unconditionally so that the load doesn't actually depend on the
|
|
// conflict rate
|
|
ConflictSet::WriteRange w;
|
|
w.begin.p = (const uint8_t *)write.data();
|
|
w.begin.len = write.size();
|
|
w.end.len = 0;
|
|
|
|
addBytes += write.size();
|
|
|
|
timer = now();
|
|
cs.addWrites(&w, 1, ++version);
|
|
addTime += now() - timer;
|
|
|
|
write = {};
|
|
reads.clear();
|
|
|
|
if (cs.getBytes() > peakMemory) {
|
|
peakMemory = cs.getBytes();
|
|
}
|
|
|
|
timer = now();
|
|
cs.setOldestVersion(version - 10000);
|
|
gcTime += now() - timer;
|
|
}
|
|
}
|
|
munmap((void *)mapOriginal, sizeOriginal);
|
|
close(fd);
|
|
}
|
|
|
|
ConflictSet::MetricsV1 *metrics;
|
|
int metricsCount;
|
|
cs.getMetricsV1(&metrics, &metricsCount);
|
|
for (int i = 0; i < metricsCount; ++i) {
|
|
fprintf(stderr, "# HELP %s %s\n", metrics[i].name, metrics[i].help);
|
|
fprintf(stderr, "# TYPE %s %s\n", metrics[i].name,
|
|
metrics[i].type == metrics[i].Counter ? "counter" : "gauge");
|
|
fprintf(stderr, "%s %g\n", metrics[i].name, metrics[i].getValue());
|
|
}
|
|
|
|
printf("Check: %g seconds, %g MB/s, Add: %g seconds, %g MB/s, Gc ratio: "
|
|
"%g%%, Peak idle memory: %g\n",
|
|
checkTime, checkBytes / checkTime * 1e-6, addTime,
|
|
addBytes / addTime * 1e-6, gcTime / (gcTime + addTime) * 1e2,
|
|
double(peakMemory));
|
|
}
|