') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })(); GitHub - VRIG-RITSEC/allocator-project-template: Template Repo For Allocator Project Including Testing Suite + Benchmarking Suite · GitHub
Skip to content

Repository files navigation

Allocator Test Suite

VRIG's custom allocator test suite and benchmarking framework.

Quick Start

  1. Clone the template:

    git clone https://github.com/CLUB-NAME/allocator-test-suite.git
    cd allocator-test-suite
  2. Setup Dependencies (Local Build): This script will clone and build mimalloc and jemalloc locally. No sudo required.

    ./setup_allocators.sh
  3. Run Tests:

    # Baseline (Glibc)
    make run-tests
    # Mimalloc
    make run-tests ALLOCATOR=allocators/mimalloc/mimalloc_wrapper.c \
    EXTRA_CFLAGS="-Iallocators/mimalloc/mimalloc_src/include" \
    LDFLAGS+="$(pwd)/build_secure/libmimalloc-secure.a -lpthread -lrt"# Jemalloc
    make run-tests ALLOCATOR=allocators/jemalloc/jemalloc_wrapper.c \
    EXTRA_CFLAGS="-Iallocators/jemalloc/jemalloc_src/include/jemalloc" \
    LDFLAGS+="$(pwd)/allocators/jemalloc/jemalloc_src/lib/libjemalloc.a -lpthread -ldl"

Directory Structure

allocator-test-suite/
├── include/
│ ├── allocator.h # Allocator interface (from spec)
│ ├── test_harness.h # Test framework utilities
│ └── benchmark.h # Benchmark infrastructure
├── src/
│ ├── tests/
│ │ ├── test_correctness.c # TC-BASIC, TC-SIZE, TC-ALIGN, TC-REALLOC, TC-CALLOC
│ │ ├── test_stress.c # TC-STRESS-001 through TC-STRESS-006
│ │ ├── test_edge.c # TC-EDGE-001 through TC-EDGE-010
│ │ └── test_fragmentation.c # TC-FRAG-001 through TC-FRAG-004
│ ├── benchmarks/
│ │ └── bench_synthetic.c # WL-SYN-001 through WL-SYN-010
│ └── harness/
│ ├── main_tests.c # Test runner entry point
│ └── main_bench.c # Benchmark runner entry point
├── allocators/
│ └── glibc/
│ └── glibc_allocator.c # Default glibc wrapper
├── Makefile
└── README.md

Integrating Your Allocator

Step 1: Implement the Interface

Your allocator must export an allocator_t structure. Here's the minimal template:

// myalloc.c#include"allocator.h"// Implement required functionsstaticvoid*myalloc_malloc(size_tsize) { /* ... */ }
staticvoidmyalloc_free(void*ptr) { /* ... */ }
staticvoid*myalloc_realloc(void*ptr, size_tsize) { /* ... */ }
staticvoid*myalloc_calloc(size_tnmemb, size_tsize) { /* ... */ }
staticintmyalloc_init(void) { return0; }
staticvoidmyalloc_teardown(void) { }
// Export allocator structureallocator_tmyalloc_allocator= {
.malloc=myalloc_malloc,
.free=myalloc_free,
.realloc=myalloc_realloc,
.calloc=myalloc_calloc,
// Optional (set to NULL if not implemented)
.memalign=NULL,
.aligned_alloc=NULL,
.usable_size=NULL,
.print_stats=NULL,
.validate_heap=NULL,
.get_stats=NULL,
// Lifecycle
.init=myalloc_init,
.teardown=myalloc_teardown,
// Metadata
.name="myalloc",
.author="Your Name",
.version="1.0.0",
.description="My custom allocator",
.memory_backend="mmap",
.features= {
.thread_safe= false,
.min_alignment=16,
.max_alignment=4096,
},
};
// Override the default allocator getterallocator_t*get_test_allocator(void) {
return&myalloc_allocator;
}
allocator_t*get_bench_allocator(void) {
return&myalloc_allocator;
}

Step 2: Build and Test

# Point to your allocator source
make ALLOCATOR=path/to/myalloc.c run-tests
# Run with debug mode (AddressSanitizer)
make debug ALLOCATOR=path/to/myalloc.c run-tests
# Run benchmarks
make MODE=bench ALLOCATOR=path/to/myalloc.c run-bench

Test Suites

Correctness Tests (29 tests)

  • TC-BASIC-001 to 005: Basic malloc/free operations
  • TC-SIZE-001 to 005: Size handling (1B to 256MB)
  • TC-ALIGN-001 to 003: Alignment verification
  • TC-REALLOC-001 to 007: Realloc semantics
  • TC-CALLOC-001 to 004: Calloc semantics
  • TC-USABLE-001 to 002: usable_size (if implemented)

Stress Tests (6 tests)

  • TC-STRESS-001: Random malloc/free (1M ops)
  • TC-STRESS-002: LIFO pattern (1M ops)
  • TC-STRESS-003: FIFO pattern (1M ops)
  • TC-STRESS-004: Realloc chains (100K ops)
  • TC-STRESS-005: Peak memory cycling (100 cycles)
  • TC-STRESS-006: 100K simultaneous allocations

Edge Case Tests (10 tests)

  • TC-EDGE-001 to 002: SIZE_MAX handling
  • TC-EDGE-003: 100K × 1-byte allocations
  • TC-EDGE-004: Page boundary allocations
  • TC-EDGE-005: Rapid init/teardown cycles
  • TC-EDGE-006 to 010: Various edge cases

Fragmentation Tests (4 tests)

  • TC-FRAG-001: Swiss cheese pattern
  • TC-FRAG-002: Sawtooth pattern
  • TC-FRAG-003: Size class thrashing
  • TC-FRAG-004: Long-running simulation

Benchmarks

Synthetic Workloads

IDDescriptionIterations
WL-SYN-001Small fixed 64B, immediate free10M
WL-SYN-002Small random 16-256B10M
WL-SYN-003Medium fixed 4KB1M
WL-SYN-004Medium random 1-64KB1M
WL-SYN-005Large fixed 1MB100K
WL-SYN-006Large random 64KB-4MB100K
WL-SYN-007Mixed power-law, batch free10M
WL-SYN-008Realloc grow chain 16B→4KB1M
WL-SYN-009Realloc shrink chain 4KB→16B1M
WL-SYN-010Calloc random 16-4KB1M

Benchmark Options

# Run all workloads
./bin/run_bench --all
# Run quick subset
./bin/run_bench --quick
# Run specific workload
./bin/run_bench --workload=WL-SYN-001
# Multiple runs for statistical significance
./bin/run_bench --runs=10
# CSV output for analysis
./bin/run_bench --csv > results.csv

Build Options

VariableDescription
ALLOCATOR=pathPath to custom allocator source
MODE=debug-O0 -g3 with ASan/UBSan
MODE=release-O2 -DNDEBUG
MODE=bench-O3 -march=native -DNDEBUG
ARGS=...Pass arguments to runner

Comparing Allocators

# Test glibc baseline
make run-bench --csv > results_glibc.csv
# Test your allocator
make ALLOCATOR=../myalloc/myalloc.c run-bench --csv > results_myalloc.csv
# Compare
diff results_glibc.csv results_myalloc.csv

Debugging Tips

  1. Run with sanitizers:

    make debug run-tests
  2. Run specific test suite:

    make run-tests ARGS='--correctness'
    make run-tests ARGS='--stress'
  3. Use Valgrind:

    make release
    valgrind --leak-check=full ./bin/run_tests
  4. Profile with perf:

    make MODE=bench bench
    perf record ./bin/run_bench --workload=WL-SYN-001
    perf report

Adding New Tests

  1. Create test function in appropriate test_*.c file:

    statictest_result_ttest_new_001(allocator_t*alloc) {
    // Your testTEST_ASSERT(condition, "message");
    returnTEST_PASS;
    }
  2. Add to test registration array:

    test_case_tmy_tests[] = {
    {"TC-NEW-001", "description", test_new_001},
    };

About

Template Repo For Allocator Project Including Testing Suite + Benchmarking Suite

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages