Skip to content

Instantly share code, notes, and snippets.

@jweinst1
Last active January 23, 2026 01:15
Show Gist options
  • Select an option

  • Save jweinst1/e0119aabc6fcee3ee9d1134154f3d1ea to your computer and use it in GitHub Desktop.

Select an option

Save jweinst1/e0119aabc6fcee3ee9d1134154f3d1ea to your computer and use it in GitHub Desktop.
Shows performance of TLB mmap writes across 1, 100, and 1024 pages
#include <iostream>
#include <vector>
#include <unordered_map>
#include <random>
#include <chrono>
#include <cstdint>
#include <limits>
#include <cstring>
#include <cstdlib>
#include <filesystem>
#include <regex>
#include <optional>
#include <string>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
struct IdGen {
std::random_device rd;
std::mt19937 gen;
std::uniform_int_distribution<uint64_t> distrib;
IdGen(): rd(), gen(rd()), distrib(std::numeric_limits<uint64_t>::min(),
std::numeric_limits<uint64_t>::max()) {}
uint64_t next() {
return static_cast<uint64_t>(distrib(gen));
}
};
// page_size = sysconf(_SC_PAGESIZE);
// file backed void* mapResult = mmap(nullptr, hf.file_size, PROT_READ | PROT_WRITE, MAP_SHARED, hf.fd, 0);
// memory ptr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
/**
* static bool byteVectorToFile(const std::vector<unsigned char>& bytes, const std::string& path) {
FILE* fp = std::fopen(path.c_str(), "wb+");
if (fp == nullptr) {
return false;
}
std::fwrite(bytes.data(), bytes.size(), 1, fp);
std::fclose(fp);
return true;
}
//int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
// 2. Set the file size to the desired length using ftruncate.
// This efficiently creates a file with a "hole" filled with implicit null bytes.
if (ftruncate(fd, filesize) == -1) {
perror("ftruncate");
close(fd);
exit(EXIT_FAILURE);
}
if (lseek(fd, 0, SEEK_SET) == -1) {
perror("lseek (rewind)");
close(fd);
exit(EXIT_FAILURE);
}
* */
static size_t getTlbEntryCount() {
long page_size = sysconf(_SC_PAGESIZE);
size_t perPageSize = page_size / 8192;
if (perPageSize == 4)
return 2048;
if (perPageSize == 1)
return 8192;
if (perPageSize == 2)
return 4096;
return (size_t)-1;
}
static void* allocateTestPage(size_t pageCount) {
long page_size = sysconf(_SC_PAGESIZE);
size_t totalSize = page_size * pageCount;
void* ptr = mmap(NULL, totalSize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (ptr == MAP_FAILED) {
abort();
}
madvise(ptr, totalSize, MADV_RANDOM);
return ptr;
}
static void writeMappedTest_1() {
long page_size = sysconf(_SC_PAGESIZE);
static constexpr size_t testPageSize = 1;
static constexpr size_t testSize = 10000000;
const size_t entryCount = (page_size * testPageSize) / sizeof(uint64_t);
printf("Using page size %ld, entry count %zu\n", page_size, entryCount);
IdGen gens;
std::vector<uint64_t> nums;
for (int i = 0; i < testSize; ++i)
{
nums.push_back(gens.next() % entryCount);
}
void* myPage = allocateTestPage(testPageSize);
uint64_t* myWriter = (uint64_t*)myPage;
auto start = std::chrono::high_resolution_clock::now();
for (int i = 0; i < testSize; ++i)
{
myWriter[nums[i]] = i;
}
auto end = std::chrono::high_resolution_clock::now();
std::cout << " 1 page test " << std::chrono::duration_cast<std::chrono::microseconds>(end - start).count() << "us\n";
}
static void writeMappedTest_2() {
long page_size = sysconf(_SC_PAGESIZE);
static constexpr size_t testPageSize = 100;
static constexpr size_t testSize = 10000000;
const size_t entryCount = (page_size * testPageSize) / sizeof(uint64_t);
printf("Using page size %ld, entry count %zu\n", page_size, entryCount);
IdGen gens;
std::vector<uint64_t> nums;
for (int i = 0; i < testSize; ++i)
{
nums.push_back(gens.next() % entryCount);
}
void* myPage = allocateTestPage(testPageSize);
uint64_t* myWriter = (uint64_t*)myPage;
auto start = std::chrono::high_resolution_clock::now();
for (int i = 0; i < testSize; ++i)
{
myWriter[nums[i]] = i;
}
auto end = std::chrono::high_resolution_clock::now();
std::cout << " 100 page test " << std::chrono::duration_cast<std::chrono::microseconds>(end - start).count() << "us\n";
}
static void writeMappedTest_3() {
long page_size = sysconf(_SC_PAGESIZE);
static constexpr size_t testPageSize = 1024;
static constexpr size_t testSize = 10000000;
const size_t entryCount = (page_size * testPageSize) / sizeof(uint64_t);
printf("Using page size %ld, entry count %zu\n", page_size, entryCount);
IdGen gens;
std::vector<uint64_t> nums;
for (int i = 0; i < testSize; ++i)
{
nums.push_back(gens.next() % entryCount);
}
void* myPage = allocateTestPage(testPageSize);
uint64_t* myWriter = (uint64_t*)myPage;
auto start = std::chrono::high_resolution_clock::now();
for (int i = 0; i < testSize; ++i)
{
myWriter[nums[i]] = i;
}
auto end = std::chrono::high_resolution_clock::now();
std::cout << " 1024 page test " << std::chrono::duration_cast<std::chrono::microseconds>(end - start).count() << "us\n";
}
int main(int argc, char const *argv[])
{
long page_size = sysconf(_SC_PAGESIZE);
std::printf("%ld\n", page_size);
writeMappedTest_1();
writeMappedTest_2();
writeMappedTest_3();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment