Skip to content

Instantly share code, notes, and snippets.

@adamwespiser
Created May 18, 2025 03:59
Show Gist options
  • Save adamwespiser/7deb191139dcc6b900a81eebef34facc to your computer and use it in GitHub Desktop.
Save adamwespiser/7deb191139dcc6b900a81eebef34facc to your computer and use it in GitHub Desktop.
Translation Lookaside Buffer Demonstration
required_packages <- c("ggplot2", "scales")
for (pkg in required_packages) {
if (!requireNamespace(pkg, quietly = TRUE)) {
cat(sprintf("Installing missing package: %s\n", pkg))
install.packages(pkg)
}
library(pkg, character.only = TRUE)
}
n <- 300
run_test <- function(mode) {
times <- numeric(n)
for (i in 1:n) {
output <- system2("./tlb_test", args = mode, stdout = TRUE, stderr = TRUE)
# Extract the elapsed time using regex
time_line <- grep("Elapsed time", output, value = TRUE)
time_sec <- as.numeric(sub(".*Elapsed time: ([0-9.]+) seconds.*", "\\1", time_line))
times[i] <- time_sec
}
return(data.frame(time = times, mode = mode))
}
set.seed(42) # For reproducibility
cat("Running hit test...\n")
hit_data <- run_test("hit")
cat("Running miss test...\n")
miss_data <- run_test("miss")
cat("Plotting data...\n")
all_data <- rbind(hit_data, miss_data)
ggplot_obj <- ggplot(all_data, aes(x = time, fill = mode)) +
geom_density(alpha = 0.6) +
scale_y_continuous(trans = pseudo_log_trans(base = 10)) +
labs(title = "TLB Timing Distribution (Hit vs Miss)",
x = "Elapsed Time (seconds)",
y = "Log-like Density")
ggsave("tlb_plot.png", plot = ggplot_obj, width = 8, height = 5)
cat("Plot saved to tlb_plot.png\n")
ggplot_obj <- ggplot(all_data, aes(x = mode, y = time, fill = mode)) +
geom_boxplot(outlier.shape = 21, alpha = 0.7, width = 0.5) +
labs(title = "TLB Access Time Comparison",
x = "Mode",
y = "Elapsed Time (seconds)")
ggsave("tlb_boxplot.png", plot = ggplot_obj, width = 8, height = 5)
cat("Plot saved to tlb_boxplot.png\n")
#!/bin/bash
set -e # Exit on error
echo "🔨 Compiling tlb_test.c..."
clang -O2 -o tlb_test tlb.c
echo "📈 Running R benchmark and plot..."
Rscript plot_tlb.R
echo "🖼️ Opening plot..."
open tlb_boxplot.png
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>
#include <time.h>
#define PAGE_SIZE 4096
#define NUM_PAGES_HIT 4
#define NUM_PAGES_MISS 8192
#define TOTAL_ACCESSES 8192*2
double get_time_sec() {
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return ts.tv_sec + ts.tv_nsec / 1e9;
}
int main(int argc, char *argv[]) {
if (argc != 2) {
fprintf(stderr, "Usage: %s [hit|miss]\n", argv[0]);
return 1;
}
int num_pages = 0;
if (strcmp(argv[1], "hit") == 0) {
num_pages = NUM_PAGES_HIT;
} else if (strcmp(argv[1], "miss") == 0) {
num_pages = NUM_PAGES_MISS;
} else {
fprintf(stderr, "Invalid mode. Use 'hit' or 'miss'.\n");
return 1;
}
size_t region_size = num_pages * PAGE_SIZE;
char *region = mmap(NULL, region_size, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (region == MAP_FAILED) {
perror("mmap");
return 1;
}
// Touch each page to ensure it's mapped into memory
for (int i = 0; i < num_pages; i++) {
region[i * PAGE_SIZE] = 1;
}
volatile char sink;
double start = get_time_sec();
if (num_pages == NUM_PAGES_HIT) {
// Access a few pages repeatedly
for (int i = 0; i < TOTAL_ACCESSES; i++) {
sink = region[(i % num_pages) * PAGE_SIZE];
}
} else {
// Access many unique pages
for (int i = 0; i < TOTAL_ACCESSES; i++) {
sink = region[(i % num_pages) * PAGE_SIZE];
}
}
double end = get_time_sec();
printf("Mode: %s | Elapsed time: %.6f seconds\n", argv[1], end - start);
munmap(region, region_size);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment