Skip to content
Open
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
1 change: 1 addition & 0 deletions demo/benchmarker/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
gluc main.glu
40 changes: 40 additions & 0 deletions demo/benchmarker/compute.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import Foundation
import CryptoKit

/// Compute SHA256 hash of data
public func hashBytes(
data: UnsafeRawPointer,
len: Int,
output: UnsafeMutableRawPointer
) {
let buffer = UnsafeRawBufferPointer(start: data, count: len)
let digest = SHA256.hash(data: buffer)
digest.withUnsafeBytes { bytes in
output.copyMemory(from: bytes.baseAddress!, byteCount: 32)
}
}

/// Verify if data matches expected hash
public func verifyHash(
data: UnsafeRawPointer,
len: Int,
expected: UnsafeRawPointer
) -> Bool {
let buffer = UnsafeRawBufferPointer(start: data, count: len)
let digest = SHA256.hash(data: buffer)

let expectedBuffer = UnsafeRawBufferPointer(start: expected, count: 32)
return digest.withUnsafeBytes { actual in
return actual.elementsEqual(expectedBuffer)
}
}

/// Compare two hashes for equality
public func compareHashes(
hash1: UnsafeRawPointer,
hash2: UnsafeRawPointer
) -> Bool {
let buffer1 = UnsafeRawBufferPointer(start: hash1, count: 32)
let buffer2 = UnsafeRawBufferPointer(start: hash2, count: 32)
return buffer1.elementsEqual(buffer2)
}
19 changes: 19 additions & 0 deletions demo/benchmarker/compute.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
const std = @import("std");
const sha256 = std.crypto.hash.sha2.Sha256;

/// Compute SHA256 hash of data
export fn hashBytes(data: [*]const u8, len: usize, output: *[32]u8) void {
sha256.hash(data[0..len], output, .{});
}

/// Verify if data matches expected hash
export fn verifyHash(data: [*]const u8, len: usize, expected: *const [32]u8) bool {
var actual: [32]u8 = undefined;
sha256.hash(data[0..len], &actual, .{});
return std.mem.eql(u8, &actual, expected);
}

/// Compare two hashes for equality
export fn compareHashes(hash1: *const [32]u8, hash2: *const [32]u8) bool {
return std.mem.eql(u8, hash1, hash2);
}
17 changes: 17 additions & 0 deletions demo/benchmarker/hexprint.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@

#![no_main]

/// Print byte slice as hex to stdout
#[no_mangle]
pub fn print_hex(data: &[u8]) {
for byte in data {
print!("{:02x}", byte);
}
println!();
}

/// Print 32-byte hash array as hex to stdout
#[no_mangle]
pub fn print_hash(hash: &[u8; 32]) {
print_hex(hash);
}
40 changes: 40 additions & 0 deletions demo/benchmarker/main.glu
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import timer::Timer;

@file_extension("zig") import compute as compute_zig;
@file_extension("swift") import compute::compute as compute_swift;

import hexprint::hexprint;
import random::random;

let debug_print: Bool = true;

func doWork() {
var data: UInt8[100];
let length: UInt64 = 100;
for i in 0..<1000000 {
random::fill_random(data, length);
var zig: UInt8[32] = {0};
var swift: UInt8[32] = {0};
compute_zig::hashBytes(data, length, &zig);
compute_swift::hashBytes({(&data) as *Char}, {length}, {&swift as *Char});
std::assert(compute_zig::verifyHash(data, length, &swift));
std::assert(compute_swift::verifyHash({(&data) as *Char}, {length}, {&zig as *Char}));
if debug_print {
std::printf("Iteration %d:\n", i);
std::print("Swift hash:");
hexprint::print_hash(&swift);
std::print("Zig hash:");
hexprint::print_hash(&zig);
}
}
}

func main() {
let timer = Timer::getInstance();

let handle = Timer::start(timer);
doWork();
Timer::stop(timer, handle);

std::printf("Elapsed time: %lldms\n", Timer::getElapsed(timer, handle));
}
10 changes: 10 additions & 0 deletions demo/benchmarker/random.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import std.random;

/// Fill array with random bytes
void fill_random(ubyte* data, size_t len) {
auto rng = Random(unpredictableSeed);
foreach (i; 0 .. len) {
data[i] = cast(ubyte)(rng.front % 256);
rng.popFront();
}
}
2 changes: 2 additions & 0 deletions demo/benchmarker/setup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export PATH="$(cd ../../build/tools/gluc && pwd):/opt/homebrew/opt/llvm@20/bin/:$PATH"
export GLU_LINKER=/usr/bin/clang++
161 changes: 161 additions & 0 deletions demo/benchmarker/timer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
#include <chrono>
#include <vector>

using Clock = std::chrono::steady_clock;
using TimePoint = std::chrono::time_point<Clock>;
using Duration = std::chrono::milliseconds;

// Structure to represent a timer interval
struct TimerInterval {
TimePoint startTime;
TimePoint endTime;
bool _isRunning;

TimerInterval();

/// @brief Mark the interval as complete
void stop();

/// @brief Check if the interval is still running
/// @return True if active, false otherwise
bool isRunning() const;

/// @brief Get the elapsed time for this interval
/// @return Duration in milliseconds
Duration getElapsed() const;
};

/// @brief Singleton timer class for tracking time intervals
class Timer {
std::vector<TimerInterval> _intervals;

Timer();

public:
Timer(Timer const &) = delete;
Timer &operator=(Timer const &) = delete;

/// @brief Get the singleton instance
/// @return Reference to the global Timer instance
static Timer &getInstance();

/// @brief Start a new timer interval
/// @return Index of the newly created interval
size_t start();

/// @brief Stop a specific timer interval
/// @param index The index of the interval to stop
/// @return True if interval was found and stopped, false otherwise
bool stop(size_t index);

/// @brief Get elapsed time for a specific interval
/// @param index The index of the interval
/// @return Duration in milliseconds, or 0 if index is invalid
Duration getElapsed(size_t index) const;

/// @brief Get total elapsed time across all intervals
/// @return Total duration in milliseconds
Duration getTotalElapsed() const;

/// @brief Count currently active intervals
/// @return Number of running intervals
size_t countActive() const;

/// @brief Get all intervals
/// @return Vector of all timer intervals
std::vector<TimerInterval> const &getIntervals() const;

/// @brief Reset all intervals
void reset();
};

// TimerInterval method definitions
TimerInterval::TimerInterval()
: startTime(Clock::now()), endTime(), _isRunning(true)
{
}

void TimerInterval::stop()
{
endTime = Clock::now();
_isRunning = false;
}

bool TimerInterval::isRunning() const
{
return _isRunning;
}

Duration TimerInterval::getElapsed() const
{
TimePoint end = _isRunning ? Clock::now() : endTime;
return std::chrono::duration_cast<Duration>(end - startTime);
}

// Timer method definitions
Timer::Timer() { }

Timer &Timer::getInstance()
{
static Timer *_instance = nullptr;
if (!_instance) {
_instance = new Timer();
}
return *_instance;
}

size_t Timer::start()
{
_intervals.emplace_back();
return _intervals.size() - 1;
}

bool Timer::stop(size_t index)
{
if (index >= _intervals.size()) {
return false;
}
if (!_intervals[index].isRunning()) {
return false;
}
_intervals[index].stop();
return true;
}

Duration Timer::getElapsed(size_t index) const
{
if (index >= _intervals.size()) {
return Duration(0);
}
return _intervals[index].getElapsed();
}

Duration Timer::getTotalElapsed() const
{
Duration total(0);
for (auto const &interval : _intervals) {
total += interval.getElapsed();
}
return total;
}

size_t Timer::countActive() const
{
size_t count = 0;
for (auto const &interval : _intervals) {
if (interval.isRunning()) {
count++;
}
}
return count;
}

std::vector<TimerInterval> const &Timer::getIntervals() const
{
return _intervals;
}

void Timer::reset()
{
_intervals.clear();
}
34 changes: 34 additions & 0 deletions demo/comparison/via-c/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
.PHONY: all clean run

CC = clang
DC = ldc2
ZIG = zig

CFLAGS = -O3
DFLAGS = -O3
ZIGFLAGS = -O ReleaseFast

TARGET = a.out
C_SRC = main.c
D_SRC = random.d
ZIG_SRC = compute.zig

D_OBJ = random.o
ZIG_OBJ = compute.o

all: $(TARGET)

$(D_OBJ): $(D_SRC)
$(DC) $(DFLAGS) -c $(D_SRC) -of=$(D_OBJ)

$(ZIG_OBJ): $(ZIG_SRC)
$(ZIG) build-obj $(ZIG_SRC) $(ZIGFLAGS) -femit-bin=$(ZIG_OBJ)

$(TARGET): $(C_SRC) $(D_OBJ) $(ZIG_OBJ)
$(DC) $(C_SRC) $(D_OBJ) $(ZIG_OBJ) -of=$(TARGET) -L-w

run: $(TARGET)
time ./$(TARGET)

clean:
rm -f $(TARGET) $(D_OBJ) $(ZIG_OBJ)
19 changes: 19 additions & 0 deletions demo/comparison/via-c/compute.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
const std = @import("std");
const sha256 = std.crypto.hash.sha2.Sha256;

/// Compute SHA256 hash of data
export fn hashBytes(data: [*]const u8, len: usize, output: *[32]u8) void {
sha256.hash(data[0..len], output, .{});
}

/// Verify if data matches expected hash
export fn verifyHash(data: [*]const u8, len: usize, expected: *const [32]u8) bool {
var actual: [32]u8 = undefined;
sha256.hash(data[0..len], &actual, .{});
return std.mem.eql(u8, &actual, expected);
}

/// Compare two hashes for equality
export fn compareHashes(hash1: *const [32]u8, hash2: *const [32]u8) bool {
return std.mem.eql(u8, hash1, hash2);
}
22 changes: 22 additions & 0 deletions demo/comparison/via-c/main.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#include <stddef.h>
#include <stdint.h>

// External function declarations from Zig (compute.zig)
extern void hashBytes(uint8_t const *data, size_t len, uint8_t output[32]);

// External function declarations from D (random.d)
extern void fill_random(uint8_t *data, size_t len);

int main()
{
for (int i = 0; i < 1000000; i++) {
uint8_t data[100];
size_t length = 100;
uint8_t hash[32] = { 0 };

fill_random(data, length);
hashBytes(data, length, hash);
}

return 0;
}
10 changes: 10 additions & 0 deletions demo/comparison/via-c/random.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import std.random;

/// Fill array with random bytes
extern(C) void fill_random(ubyte* data, size_t len) {
auto rng = Random(unpredictableSeed);
foreach (i; 0 .. len) {
data[i] = cast(ubyte)(rng.front % 256);
rng.popFront();
}
}
Loading
Loading