diff --git a/CMakeLists.txt b/CMakeLists.txt index e9753fb..6750857 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -189,6 +189,9 @@ if(BUILD_TESTING) # "-fsanitize=address,undefined,fuzzer") # target_link_options(conflict_set_bench PRIVATE # "-fsanitize=address,undefined,fuzzer") + + add_executable(conflict_set_bench_e2e RealDataBench.cpp) + target_link_libraries(conflict_set_bench_e2e PRIVATE ${PROJECT_NAME}) endif() # packaging diff --git a/RealDataBench.cpp b/RealDataBench.cpp new file mode 100644 index 0000000..f1c5fe7 --- /dev/null +++ b/RealDataBench.cpp @@ -0,0 +1,114 @@ +#include + +#include +#include +#include +#include +#include +#include + +double now() { + return std::chrono::duration_cast( + 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; + + ConflictSet cs{0}; + int64_t version = 0; + double timer = 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); + + using StringView = std::basic_string_view; + + StringView write; + std::vector reads; + std::vector readRanges; + std::vector results; + + for (uint8_t *end = (uint8_t *)memchr(begin, '\n', size); end != nullptr;) { + StringView line{begin, static_cast(end - begin)}; + size -= end - begin + 1; + begin = end + 1; + end = (uint8_t *)memchr(begin, '\n', size); + + if (line.size() > 0 && line[0] == 'P') { + write = std::move(line); + } else if (line.size() > 0 && line[0] == 'L') { + reads.push_back(std::move(line)); + } 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(); + 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.writeVersion = ++version; + w.begin.p = (const uint8_t *)write.data(); + w.begin.len = write.size(); + w.end.len = 0; + + timer = now(); + cs.addWrites(&w, 1); + addTime += now() - timer; + + write = {}; + reads.clear(); + + timer = now(); + cs.setOldestVersion(version - 10000); + gcTime += now() - timer; + } + } + close(fd); + } + + printf("Check: %g, Add: %g, Gc: %g\n", checkTime, addTime, gcTime); +} \ No newline at end of file