Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 41 additions & 0 deletions .github/workflows/bazel.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
name: Bazel

on:
pull_request:
branches:
- main
push:
branches:
- main

jobs:
test:
runs-on: ubuntu-latest

defaults:
run:
# MODULE.bazel and .bazelversion live in src/
working-directory: src

steps:
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2

- uses: bazel-contrib/setup-bazel@c5acdfb288317d0b5c0bbd7a396a3dc868bb0f86 # 0.19.0
with:
bazelisk-cache: true
disk-cache: ${{ github.workflow }}
repository-cache: true
# Pull requests only restore caches, pushes to main refresh them
cache-save: ${{ github.event_name == 'push' }}
bazelrc: |
common --announce_rc
common --color=yes

- name: Bazel version
run: bazel version

- name: Build
run: bazel build //...

- name: Test
run: bazel test //... --test_output=errors
12 changes: 12 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Bazel
*~
bazel-*
*MODULE.bazel.lock
/.ijwb/
/.aswb/
/.clwb/

# IDEs
.idea
.vscode
.vs
32 changes: 32 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,34 @@
# memcopy-bench
DevTools 2026 Research Project. Violet Team

# Setup

We use [Bazel](https://bazel.build/install) to build, run and test our project.
The Bazel version is pinned in `src/.bazelversion`, use
[Bazelisk](https://github.com/bazelbuild/bazelisk) to get the right one.

All commands below are run from `src/`:
```bash
cd src/
```

Optimized build mode (`-c opt`) is enabled by default in `src/.bazelrc`.

**Build:**
```bash
bazel build //lib:memcpy_bench # build benchmark lib only
bazel build //main:main # build main binary and library
```

**Test:**
```bash
bazel test //test:memcpy_bench_test
```

**Run benchmarks:**
```bash
bazel run //main:main

# Google Benchmark flags are passed after `--`
bazel run //main:main -- --benchmark_filter='BM_Memcpy/4096' --benchmark_format=json
```
1 change: 1 addition & 0 deletions src/.bazelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
build -c opt
1 change: 1 addition & 0 deletions src/.bazelversion
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
9.3.0
8 changes: 8 additions & 0 deletions src/MODULE.bazel
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# https://registry.bazel.build/modules/rules_cc
bazel_dep(name = "rules_cc", version = "0.2.26")

# https://registry.bazel.build/modules/googletest
bazel_dep(name = "googletest", version = "1.18.0.bcr.1", dev_dependency = True)

# https://registry.bazel.build/modules/google_benchmark
bazel_dep(name = "google_benchmark", version = "1.9.5")
14 changes: 14 additions & 0 deletions src/lib/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
load("@rules_cc//cc:cc_library.bzl", "cc_library")

cc_library(
name = "memcpy_bench",
srcs = ["memcpy_bench.cc"],
hdrs = ["memcpy_bench.h"],
deps = [
"@google_benchmark//:benchmark",
],
visibility = [
"//main:__pkg__",
"//test:__pkg__",
],
)
54 changes: 54 additions & 0 deletions src/lib/memcpy_bench.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#include "lib/memcpy_bench.h"

#include <cstring>
#include <random>

#include <benchmark/benchmark.h>

namespace memcpy_bench {

namespace {

void BM_Memcpy(benchmark::State& state) {
const auto size = static_cast<std::size_t>(state.range(0));

const std::vector<unsigned char> src = RandomBytes(size);
std::vector<unsigned char> dst(size);

for (auto _ : state) {
std::memcpy(dst.data(), src.data(), size);
benchmark::DoNotOptimize(dst.data());
benchmark::ClobberMemory();
}

state.SetBytesProcessed(static_cast<std::int64_t>(state.iterations()) *
static_cast<std::int64_t>(size));
}

}

std::vector<unsigned char> RandomBytes(std::size_t size, std::uint32_t seed) {
std::mt19937 gen(seed);
std::uniform_int_distribution<int> dist(0, 255);
std::vector<unsigned char> bytes(size);
for (auto& byte : bytes) {
byte = static_cast<unsigned char>(dist(gen));
}
return bytes;
}

int Run(int argc, char** argv) {
benchmark::RegisterBenchmark("BM_Memcpy", BM_Memcpy)
->RangeMultiplier(4)
->Range(64, 64 << 20);

benchmark::Initialize(&argc, argv);
if (benchmark::ReportUnrecognizedArguments(argc, argv)) {
return 1;
}
benchmark::RunSpecifiedBenchmarks();
benchmark::Shutdown();
return 0;
}

}
13 changes: 13 additions & 0 deletions src/lib/memcpy_bench.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#pragma once

#include <cstddef>
#include <cstdint>
#include <vector>

namespace memcpy_bench {

std::vector<unsigned char> RandomBytes(std::size_t size, std::uint32_t seed = 42);

int Run(int argc, char** argv);

}
9 changes: 9 additions & 0 deletions src/main/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
load("@rules_cc//cc:cc_binary.bzl", "cc_binary")

cc_binary(
name = "main",
srcs = glob(["*.cc"]),
deps = [
"//lib:memcpy_bench",
],
)
6 changes: 6 additions & 0 deletions src/main/main.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#include "lib/memcpy_bench.h"

int main(int argc, char **argv)
{
return memcpy_bench::Run(argc, argv);
}
11 changes: 11 additions & 0 deletions src/test/BUILD
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
load("@rules_cc//cc:cc_test.bzl", "cc_test")


cc_test(
name = "memcpy_bench_test",
srcs = glob(["*.cc"]),
deps = [
"@googletest//:gtest_main",
"//lib:memcpy_bench",
],
)
15 changes: 15 additions & 0 deletions src/test/memcpy_bench_test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#include "gtest/gtest.h"
#include "lib/memcpy_bench.h"

TEST(RandomBytesTest, ReturnsRequestedSize) {
EXPECT_EQ(memcpy_bench::RandomBytes(0).size(), 0u);
EXPECT_EQ(memcpy_bench::RandomBytes(1024).size(), 1024u);
}

TEST(RandomBytesTest, SameSeedGivesSameBytes) {
EXPECT_EQ(memcpy_bench::RandomBytes(256, 7), memcpy_bench::RandomBytes(256, 7));
}

TEST(RandomBytesTest, DifferentSeedsGiveDifferentBytes) {
EXPECT_NE(memcpy_bench::RandomBytes(256, 1), memcpy_bench::RandomBytes(256, 2));
}
Loading