Skip to content

Commit bac836f

Browse files
authored
chore: add query and reflection benchmarks (#386)
# Summary - Adds more interesting benchmarks around querying and reflection, revealing slower parts of BMS and/or Bevy - Re-create all plots based on benchmarks present every push to main
1 parent 570df08 commit bac836f

File tree

20 files changed

+664
-9
lines changed

20 files changed

+664
-9
lines changed

assets/benchmarks/function/call.lua

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
function bench()
2+
noop()
3+
end

assets/benchmarks/function/call.rhai

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
fn bench(){
2+
noop.call();
3+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
function bench()
2+
noop_4_args(1,"asd",{1,2,3}, {asd = 1})
3+
end
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
fn bench(){
2+
noop_4_args.call(1,"asd",[1,2,3],#{ asd: 1});
3+
}
+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
2+
reseed()
3+
4+
local matrix = nil
5+
local vector = nil
6+
function pre_bench()
7+
-- generate random 3x3 matrix and 3x1 vec
8+
vector = Vec3.new(random(1,999), random(1,999), random(1,999))
9+
matrix = Mat3.from_cols(
10+
Vec3.new(random(1,999), random(1,999), random(1,999)),
11+
Vec3.new(random(1,999), random(1,999), random(1,999)),
12+
Vec3.new(random(1,999), random(1,999), random(1,999))
13+
)
14+
end
15+
16+
function bench()
17+
local mul = matrix * vector
18+
local add = matrix + vector
19+
local div = vector / matrix
20+
end
+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
2+
reseed.call();
3+
4+
let matrix = ();
5+
let vector = ();
6+
fn pre_bench(){
7+
vector = Vec3.new_.call(random.call(1,999), random.call(1,999), random.call(1,999));
8+
matrix = Mat3.from_cols.call(
9+
Vec3.new_.call(random.call(1,999), random.call(1,999), random.call(1,999)),
10+
Vec3.new_.call(random.call(1,999), random.call(1,999), random.call(1,999)),
11+
Vec3.new_.call(random.call(1,999), random.call(1,999), random.call(1,999))
12+
);
13+
}
14+
15+
fn bench() {
16+
let mul = matrix * vector;
17+
let add = matrix + vector;
18+
let div = vector / matrix;
19+
}
+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
local entity_a = world.spawn()
2+
local entity_b = world.spawn()
3+
local entity_c = world.spawn()
4+
5+
local components = {
6+
types.CompWithDefaultAndComponentData,
7+
types.CompWithFromWorldAndComponentData,
8+
types.SimpleTupleStruct,
9+
types.SimpleEnum,
10+
}
11+
12+
reseed()
13+
14+
for i = 1, 1000 do
15+
local entity = world.spawn()
16+
-- spawn 1000 entities with random components
17+
local left_to_pick = {1,2,3,4}
18+
for j = 1, 3 do
19+
local index = random_int(1, #left_to_pick)
20+
local component = components[left_to_pick[index]]
21+
table.remove(left_to_pick, index)
22+
world.add_default_component(entity, component)
23+
end
24+
end
25+
26+
function bench()
27+
for i,result in pairs(world.query()
28+
:component(types.CompWithFromWorldAndComponentData)
29+
:component(types.SimpleTupleStruct)
30+
:with(types.SimpleEnum)
31+
:without(types.CompWithDefaultAndComponentData)
32+
:build()) do
33+
34+
end
35+
end
+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
let entity_a = world.spawn_.call();
2+
let entity_b = world.spawn_.call();
3+
let entity_c = world.spawn_.call();
4+
5+
let components = [
6+
types.CompWithDefaultAndComponentData,
7+
types.CompWithFromWorldAndComponentData,
8+
types.SimpleTupleStruct,
9+
types.SimpleEnum,
10+
];
11+
12+
reseed.call();
13+
14+
for i in 1..=1000 {
15+
let entity = world.spawn_.call();
16+
// spawn 1000 entities with random components
17+
let left_to_pick = [0, 1, 2, 3];
18+
for j in 1..=3 {
19+
let index = random_int.call(1, left_to_pick.len()) - 1;
20+
let component = components[left_to_pick[index]];
21+
left_to_pick.remove(index);
22+
world.add_default_component.call(entity, component);
23+
};
24+
};
25+
26+
fn bench() {
27+
for (result, i) in world.query.call()
28+
.component.call(types.CompWithFromWorldAndComponentData)
29+
.component.call(types.SimpleTupleStruct)
30+
.with_.call(types.SimpleEnum)
31+
.without.call(types.CompWithDefaultAndComponentData)
32+
.build.call() {
33+
};
34+
}
+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
local entity_a = world.spawn()
2+
local entity_b = world.spawn()
3+
local entity_c = world.spawn()
4+
5+
local components = {
6+
types.CompWithDefaultAndComponentData,
7+
types.CompWithFromWorldAndComponentData,
8+
types.SimpleTupleStruct,
9+
types.SimpleEnum,
10+
}
11+
12+
reseed()
13+
14+
for i = 1, 100 do
15+
local entity = world.spawn()
16+
local left_to_pick = {1,2,3,4}
17+
for j = 1, 3 do
18+
local index = random_int(1, #left_to_pick)
19+
local component = components[left_to_pick[index]]
20+
table.remove(left_to_pick, index)
21+
world.add_default_component(entity, component)
22+
end
23+
end
24+
25+
function bench()
26+
for i,result in pairs(world.query()
27+
:component(types.CompWithFromWorldAndComponentData)
28+
:component(types.SimpleTupleStruct)
29+
:with(types.SimpleEnum)
30+
:without(types.CompWithDefaultAndComponentData)
31+
:build()) do
32+
33+
end
34+
end
+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
let entity_a = world.spawn_.call();
2+
let entity_b = world.spawn_.call();
3+
let entity_c = world.spawn_.call();
4+
5+
let components = [
6+
types.CompWithDefaultAndComponentData,
7+
types.CompWithFromWorldAndComponentData,
8+
types.SimpleTupleStruct,
9+
types.SimpleEnum,
10+
];
11+
12+
reseed.call();
13+
14+
for i in 1..=100 {
15+
let entity = world.spawn_.call();
16+
let left_to_pick = [0, 1, 2, 3];
17+
for j in 1..=3 {
18+
let index = random_int.call(1, left_to_pick.len()) - 1;
19+
let component = components[left_to_pick[index]];
20+
left_to_pick.remove(index);
21+
world.add_default_component.call(entity, component);
22+
};
23+
};
24+
25+
fn bench() {
26+
for (result, i) in world.query.call()
27+
.component.call(types.CompWithFromWorldAndComponentData)
28+
.component.call(types.SimpleTupleStruct)
29+
.with_.call(types.SimpleEnum)
30+
.without.call(types.CompWithDefaultAndComponentData)
31+
.build.call() {
32+
};
33+
}
+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
local entity_a = world.spawn()
2+
local entity_b = world.spawn()
3+
local entity_c = world.spawn()
4+
5+
local components = {
6+
types.CompWithDefaultAndComponentData,
7+
types.CompWithFromWorldAndComponentData,
8+
types.SimpleTupleStruct,
9+
types.SimpleEnum,
10+
}
11+
12+
reseed()
13+
14+
for i = 1, 10 do
15+
local entity = world.spawn()
16+
local left_to_pick = {1,2,3,4}
17+
for j = 1, 3 do
18+
local index = random_int(1, #left_to_pick)
19+
local component = components[left_to_pick[index]]
20+
table.remove(left_to_pick, index)
21+
world.add_default_component(entity, component)
22+
end
23+
end
24+
25+
function bench()
26+
for i,result in pairs(world.query()
27+
:component(types.CompWithFromWorldAndComponentData)
28+
:component(types.SimpleTupleStruct)
29+
:with(types.SimpleEnum)
30+
:without(types.CompWithDefaultAndComponentData)
31+
:build()) do
32+
33+
end
34+
end
+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
let entity_a = world.spawn_.call();
2+
let entity_b = world.spawn_.call();
3+
let entity_c = world.spawn_.call();
4+
5+
let components = [
6+
types.CompWithDefaultAndComponentData,
7+
types.CompWithFromWorldAndComponentData,
8+
types.SimpleTupleStruct,
9+
types.SimpleEnum,
10+
];
11+
12+
reseed.call();
13+
14+
for i in 1..=10 {
15+
let entity = world.spawn_.call();
16+
let left_to_pick = [0, 1, 2, 3];
17+
for j in 1..=3 {
18+
let index = random_int.call(1, left_to_pick.len()) - 1;
19+
let component = components[left_to_pick[index]];
20+
left_to_pick.remove(index);
21+
world.add_default_component.call(entity, component);
22+
};
23+
};
24+
25+
fn bench() {
26+
for (result, i) in world.query.call()
27+
.component.call(types.CompWithFromWorldAndComponentData)
28+
.component.call(types.SimpleTupleStruct)
29+
.with_.call(types.SimpleEnum)
30+
.without.call(types.CompWithDefaultAndComponentData)
31+
.build.call() {
32+
};
33+
}

assets/benchmarks/reflection/10.lua

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
-- create a dynamic component with n depth of fields
2+
local Component = world.register_new_component("DeepComponent");
3+
local new_entity = world.spawn();
4+
5+
reseed()
6+
7+
local keys = {
8+
"_0",
9+
"my_key",
10+
"longish_key"
11+
}
12+
13+
-- Recursively build a single nested table using the pre-selected step_keys.
14+
local function make_path(step_keys, index)
15+
if index > #step_keys then
16+
return {}
17+
end
18+
local key = step_keys[index]
19+
return { [key] = make_path(step_keys, index + 1) }
20+
end
21+
22+
23+
local current_reference = nil
24+
local steps = 10
25+
local step_keys = {}
26+
function pre_bench()
27+
step_keys = {}
28+
current_reference = nil
29+
-- Choose keys for every step.
30+
for i = 1, steps do
31+
local key = keys[random_int(1, #keys)]
32+
step_keys[i] = key
33+
end
34+
35+
-- Build the nested table.
36+
local instance = make_path(step_keys, 1)
37+
world.remove_component(new_entity, Component)
38+
world.insert_component(new_entity, Component, construct(types.DynamicComponent, {
39+
data = instance
40+
}))
41+
current_reference = world.get_component(new_entity, Component)
42+
end
43+
44+
function bench()
45+
-- reference into random key into current_reference steps times
46+
local reference = current_reference.data
47+
local current_step = 1
48+
while current_step <= steps do
49+
reference = reference[step_keys[current_step]]
50+
current_step = current_step + 1
51+
end
52+
end

assets/benchmarks/reflection/10.rhai

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
let Component = world.register_new_component.call("DeepComponent");
2+
let new_entity = world.spawn_.call();
3+
4+
reseed.call();
5+
6+
let keys = [
7+
"_0",
8+
"my_key",
9+
"longish_key"
10+
];
11+
12+
fn make_path(step_keys, index) {
13+
if index >= step_keys.len() {
14+
return #{};
15+
};
16+
let key = step_keys[index];
17+
let nested = make_path(step_keys, index + 1);
18+
let obj = #{};
19+
obj.set(key,nested);
20+
return obj;
21+
};
22+
23+
let current_reference = ();
24+
let steps = 10;
25+
let step_keys = [];
26+
27+
fn pre_bench() {
28+
step_keys = [];
29+
current_reference = ();
30+
31+
// Choose keys for every step.
32+
for i in 0 .. steps {
33+
let key = keys[random_int.call(0, keys.len() - 1)];
34+
step_keys.push(key);
35+
};
36+
37+
// Build the nested table.
38+
let instance = make_path(step_keys, 0);
39+
world.remove_component.call(new_entity, Component);
40+
world.insert_component.call(new_entity, Component, construct.call(types.DynamicComponent, #{ "data": instance }));
41+
current_reference = world.get_component.call(new_entity, Component);
42+
};
43+
44+
fn bench() {
45+
// reference into random key into current_reference steps times
46+
let reference = current_reference.data;
47+
let current_step = 0;
48+
while current_step < steps {
49+
reference = reference[step_keys[current_step]];
50+
current_step += 1;
51+
};
52+
};

0 commit comments

Comments
 (0)