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
2 changes: 2 additions & 0 deletions benchmark/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ kvlang 是被测对象,**分别在三个 kvspace 后端上各跑一遍,占
| `k_nucleotide` | 字符串 + 哈希表 | 逐字符 `ord` 入哈希表统计碱基频次 |
| `iops` | 最小寻址单元往返地板价 | 单 key 读-改-写 `a=a+1`,per-op 延迟(对齐 #204,参考基线) |
| `prime_sieve` | 计算 / 控制流密集 | 嵌套 `while` + 取模,O(n²) 内层迭代(参考基线) |
| `matmul_compact` | **数组物理形态**(compact) | 同 `matmul` 算法,矩阵落单个 `[N,N]float64`(storetype=ARRAYND,元素连续打包),对照「每元素一个 key 的散 key map」 |
| `quicksort_compact` | **数组物理形态**(compact) | 同 `quicksort` 算法,待排数组与显式栈都落单个 `[N]int64`,全程在 compact 数组里直接交换 |

kvlang 的性能瓶颈是「PC/帧/局部全落 KV 树、每步一次往返」的架构本质(见 kvlang#194 #204 #116),
不是某个热点函数;`iops`/`prime_sieve` 单独隔离出这条地板价,其余八例是跨语言等价算法对照。
Expand Down
2 changes: 1 addition & 1 deletion benchmark/cases/binary_search/binary_search.kv
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// 建 arr[i]=i,对 0..N-1 逐个二分,累加命中下标;N 由 __SCALE__ 占位(勿改逻辑)
// 期望输出(N=32 时):
// bsearch: found = 32 sum = 496
rwfunc bsearch(arr:[int64]·int64, n:int64, target:int64) -> (idx:int64) {
rwfunc bsearch(arr:*[int64]·int64, n:int64, target:int64) -> (idx:int64) {
0 -> lo
n - 1 -> hi
-1 -> idx
Expand Down
32 changes: 32 additions & 0 deletions benchmark/cases/matmul_compact/matmul_compact.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main(void) {
int n = atoi(getenv("BENCH_SCALE"));
double A[n * n], B[n * n];
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
int idx = i * n + j;
A[idx] = (double)((i + j) % 4) * 0.25 + 0.25;
B[idx] = (double)((i * 2 + j) % 4) * 0.25 + 0.25;
}
}
struct timespec t0, t1;
clock_gettime(CLOCK_MONOTONIC, &t0);
double checksum = 0.0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
double acc = 0.0;
for (int k = 0; k < n; k++)
acc += A[i * n + k] * B[k * n + j];
checksum += acc;
}
}
clock_gettime(CLOCK_MONOTONIC, &t1);
long ns = (t1.tv_sec - t0.tv_sec) * 1000000000L + (t1.tv_nsec - t0.tv_nsec);
long out = (long)(checksum * 1000000.0);
printf("matmul_compact: check = %ld\n", out);
printf("__bench_ns: %ld\n", ns);
return 0;
}
60 changes: 60 additions & 0 deletions benchmark/cases/matmul_compact/matmul_compact.kv
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// matrix multiplication benchmark(compact 形式)— 同 matmul 算法,矩阵落**单个 compact XValue**
// (`[N,N]float64`,storetype=ARRAYND,元素连续打包),而非散 key 的 `[int64]·float64` map。
// 对比点:同一算法的两种 kv 物理形态——map 每次元素访问一次 KV 往返,compact 一次 xv·at/set。
// 方阵阶 N 由 __SCALE__ 占位(O(N^3),勿改逻辑)
// 期望输出(N=6 时):
// matmul_compact: check = 82750000
rwfunc test() -> () {
__SCALE__ -> n
A:[__SCALE__,__SCALE__]float64 = []
B:[__SCALE__,__SCALE__]float64 = []
0 -> i
while (i < n) {
0 -> j
while (j < n) {
i + j -> ta
ta % 4 -> qa
float64(qa) -> qaf
qaf × 0.25 -> pa
pa + 0.25 -> av
av -> A[i, j]
i × 2 -> i2
i2 + j -> tb
tb % 4 -> qb
float64(qb) -> qbf
qbf × 0.25 -> pb
pb + 0.25 -> bv
bv -> B[i, j]
j + 1 -> j
}
i + 1 -> i
}
t0 = time·now()
0.0 -> checksum
0 -> i
while (i < n) {
0 -> j
while (j < n) {
0.0 -> acc
0 -> k
while (k < n) {
A[i, k] -> av
B[k, j] -> bv
av × bv -> pr
acc + pr -> acc
k + 1 -> k
}
checksum + acc -> checksum
j + 1 -> j
}
i + 1 -> i
}
t1 = time·now()
checksum × 1000000.0 -> scaled
int64(scaled) -> out
println("matmul_compact: check =", out)
delta = time·sub(t1, t0)
ns = time/duration·as_nanos(delta)
println("__bench_ns:", ns)
println("__bench_input: N=__SCALE__")
}
23 changes: 23 additions & 0 deletions benchmark/cases/matmul_compact/matmul_compact.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import os
import time

n = int(os.environ["BENCH_SCALE"])
A = [0.0] * (n * n)
B = [0.0] * (n * n)
for i in range(n):
for j in range(n):
idx = i * n + j
A[idx] = float((i + j) % 4) * 0.25 + 0.25
B[idx] = float((i * 2 + j) % 4) * 0.25 + 0.25
t0 = time.perf_counter_ns()
checksum = 0.0
for i in range(n):
for j in range(n):
acc = 0.0
for k in range(n):
acc += A[i * n + k] * B[k * n + j]
checksum += acc
t1 = time.perf_counter_ns()
out = int(checksum * 1000000.0)
print("matmul_compact: check =", out)
print("__bench_ns:", t1 - t0)
29 changes: 29 additions & 0 deletions benchmark/cases/matmul_compact/matmul_compact.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
use std::time::Instant;

fn main() {
let n: usize = std::env::var("BENCH_SCALE").unwrap().parse().unwrap();
let mut a = vec![0.0f64; n * n];
let mut b = vec![0.0f64; n * n];
for i in 0..n {
for j in 0..n {
let idx = i * n + j;
a[idx] = ((i + j) % 4) as f64 * 0.25 + 0.25;
b[idx] = ((i * 2 + j) % 4) as f64 * 0.25 + 0.25;
}
}
let t0 = Instant::now();
let mut checksum = 0.0f64;
for i in 0..n {
for j in 0..n {
let mut acc = 0.0f64;
for k in 0..n {
acc += a[i * n + k] * b[k * n + j];
}
checksum += acc;
}
}
let ns = t0.elapsed().as_nanos();
let out = (checksum * 1000000.0) as i64;
println!("matmul_compact: check = {}", out);
println!("__bench_ns: {}", ns);
}
44 changes: 44 additions & 0 deletions benchmark/cases/quicksort_compact/quicksort_compact.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

static void swap(long *a, long i, long j) {
long t = a[i];
a[i] = a[j];
a[j] = t;
}

static void qsort_r(long *a, long lo, long hi) {
if (lo < hi) {
long pivot = a[hi];
long i = lo - 1;
for (long j = lo; j < hi; j++) {
if (a[j] <= pivot) {
i++;
swap(a, i, j);
}
}
swap(a, i + 1, hi);
long p = i + 1;
qsort_r(a, lo, p - 1);
qsort_r(a, p + 1, hi);
}
}

int main(void) {
long n = atol(getenv("BENCH_SCALE"));
long arr[n];
long seed = 1;
for (long i = 0; i < n; i++) {
seed = (seed * 1103515245 + 12345) % 2147483648;
arr[i] = seed % 100;
}
struct timespec t0, t1;
clock_gettime(CLOCK_MONOTONIC, &t0);
qsort_r(arr, 0, n - 1);
clock_gettime(CLOCK_MONOTONIC, &t1);
long ns = (t1.tv_sec - t0.tv_sec) * 1000000000L + (t1.tv_nsec - t0.tv_nsec);
printf("qsort_compact: a0 = %ld amid = %ld alast = %ld\n", arr[0], arr[n / 2], arr[n - 1]);
printf("__bench_ns: %ld\n", ns);
return 0;
}
69 changes: 69 additions & 0 deletions benchmark/cases/quicksort_compact/quicksort_compact.kv
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// quicksort benchmark(compact 形式)— 同 quicksort 算法,待排数组与显式栈都落**单个 compact
// XValue**(`[N]int64`,storetype=ARRAYND),而非散 key 的 `[int64]·int64` map。
// 对比点:同一算法的两种 kv 物理形态。
// 数据由 LCG 确定生成,规模 N 由 __SCALE__ 占位,run.py 按扫描点替换(勿改逻辑)
// 期望输出(N=64 时):
// qsort_compact: a0 = 1 amid = 52 alast = 99
rwfunc test() -> () {
__SCALE__ -> n
arr:[__SCALE__]int64 = []
1 -> seed
0 -> i
while (i < n) {
seed × 1103515245 -> s1
s1 + 12345 -> s2
s2 % 2147483648 -> seed
seed % 100 -> v
v -> arr[i]
i + 1 -> i
}
t0 = time·now()
// 显式栈也用 compact:与待排数组一样落单个 ARRAYND XValue,全程只在 compact 数组里直接交换。
st_lo:[__SCALE__]int64 = []
st_hi:[__SCALE__]int64 = []
0 -> top
0 -> st_lo[top]
n - 1 -> st_hi[top]
top + 1 -> top
while (top > 0) {
top - 1 -> top
st_lo[top] -> lo
st_hi[top] -> hi
if (lo < hi) {
arr[hi] -> pivot
lo - 1 -> ii
lo -> jj
while (jj < hi) {
arr[jj] -> aj
if (aj <= pivot) {
ii + 1 -> ii
arr[ii] -> ai
aj -> arr[ii]
ai -> arr[jj]
}
jj + 1 -> jj
}
ii + 1 -> pp
arr[pp] -> app
pivot -> arr[pp]
app -> arr[hi]
lo -> st_lo[top]
pp - 1 -> st_hi[top]
top + 1 -> top
pp + 1 -> st_lo[top]
hi -> st_hi[top]
top + 1 -> top
}
}
t1 = time·now()
n ÷ 2 -> mid
n - 1 -> last
arr[0] -> a0
arr[mid] -> am
arr[last] -> al
println("qsort_compact: a0 =", a0, "amid =", am, "alast =", al)
delta = time·sub(t1, t0)
ns = time/duration·as_nanos(delta)
println("__bench_ns:", ns)
println("__bench_input: N=__SCALE__,seed=1")
}
32 changes: 32 additions & 0 deletions benchmark/cases/quicksort_compact/quicksort_compact.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import os
import time
import sys

sys.setrecursionlimit(10000)


def qsort(a, lo, hi):
if lo < hi:
pivot = a[hi]
i = lo - 1
for j in range(lo, hi):
if a[j] <= pivot:
i += 1
a[i], a[j] = a[j], a[i]
a[i + 1], a[hi] = a[hi], a[i + 1]
p = i + 1
qsort(a, lo, p - 1)
qsort(a, p + 1, hi)


n = int(os.environ["BENCH_SCALE"])
arr = []
seed = 1
for i in range(n):
seed = (seed * 1103515245 + 12345) % 2147483648
arr.append(seed % 100)
t0 = time.perf_counter_ns()
qsort(arr, 0, n - 1)
t1 = time.perf_counter_ns()
print("qsort_compact: a0 =", arr[0], "amid =", arr[n // 2], "alast =", arr[n - 1])
print("__bench_ns:", t1 - t0)
35 changes: 35 additions & 0 deletions benchmark/cases/quicksort_compact/quicksort_compact.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use std::time::Instant;

fn qsort(a: &mut [i64], lo: i64, hi: i64) {
if lo < hi {
let pivot = a[hi as usize];
let mut i = lo - 1;
let mut j = lo;
while j < hi {
if a[j as usize] <= pivot {
i += 1;
a.swap(i as usize, j as usize);
}
j += 1;
}
a.swap((i + 1) as usize, hi as usize);
let p = i + 1;
qsort(a, lo, p - 1);
qsort(a, p + 1, hi);
}
}

fn main() {
let n: i64 = std::env::var("BENCH_SCALE").unwrap().parse().unwrap();
let mut arr: Vec<i64> = Vec::new();
let mut seed: i64 = 1;
for _ in 0..n {
seed = (seed * 1103515245 + 12345) % 2147483648;
arr.push(seed % 100);
}
let t0 = Instant::now();
qsort(&mut arr, 0, n - 1);
let ns = t0.elapsed().as_nanos();
println!("qsort_compact: a0 = {} amid = {} alast = {}", arr[0], arr[(n / 2) as usize], arr[(n - 1) as usize]);
println!("__bench_ns: {}", ns);
}
4 changes: 4 additions & 0 deletions benchmark/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@
"hash_table": [50, 100, 200],
"matmul": [4, 6, 8],
"k_nucleotide": [3, 5, 8],
# 同一算法的 compact 形态:数组落单个 ARRAYND XValue(`[N]T`),而非每元素一个 key 的散 key map。
# 与 matmul / quicksort 同规模、同基线(native 三份与原 case 算法完全一致,仅输出标签不同)。
"matmul_compact": [4, 6, 8],
"quicksort_compact": [32, 64, 128],
}
SCALE_ENV = "BENCH_SCALE" # python/rust/c 从此环境变量读规模
SCALE_TOKEN = "__SCALE__" # kvlang 源码里的规模占位符
Expand Down
6 changes: 3 additions & 3 deletions deps.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"kvspace": "v0.2.16",
"kvspace-c": "v0.2.16",
"kvspace-durable": "v0.2.16",
"kvspace": "v0.2.17",
"kvspace-c": "v0.2.17",
"kvspace-durable": "v0.2.17",
"blockmalloc": "v0.1.4",
"slotsboxmalloc": "v0.1.5"
}
Loading
Loading