Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

C# module benchmarks #1679

Merged
merged 6 commits into from
Sep 6, 2024
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
20 changes: 12 additions & 8 deletions crates/bench/src/spacetime_module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,18 @@ use crate::{

lazy_static::lazy_static! {
pub static ref BENCHMARKS_MODULE: CompiledModule = {
// Temporarily add CARGO_TARGET_DIR override to avoid conflicts with main target dir.
// Otherwise for some reason Cargo will mark all dependencies with build scripts as
// fresh - but only if running benchmarks (if modules are built in release mode).
// See https://github.com/clockworklabs/SpacetimeDB/issues/401.
std::env::set_var("CARGO_TARGET_DIR", concat!(env!("CARGO_MANIFEST_DIR"), "/target"));
let module = CompiledModule::compile("benchmarks", CompilationMode::Release);
std::env::remove_var("CARGO_TARGET_DIR");
module
if std::env::var_os("STDB_BENCH_CS").is_some() {
CompiledModule::compile("benchmarks-cs", CompilationMode::Release)
} else {
// Temporarily add CARGO_TARGET_DIR override to avoid conflicts with main target dir.
// Otherwise for some reason Cargo will mark all dependencies with build scripts as
// fresh - but only if running benchmarks (if modules are built in release mode).
// See https://github.com/clockworklabs/SpacetimeDB/issues/401.
std::env::set_var("CARGO_TARGET_DIR", concat!(env!("CARGO_MANIFEST_DIR"), "/target"));
let module = CompiledModule::compile("benchmarks", CompilationMode::Release);
std::env::remove_var("CARGO_TARGET_DIR");
module
}
};
}

Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion crates/bindings-csharp/Codegen/Module.cs
Original file line number Diff line number Diff line change
Expand Up @@ -448,7 +448,7 @@ public static void Main() {
public static void __describe_module__(SpacetimeDB.Internal.BytesSink d) => SpacetimeDB.Internal.Module.__describe_module__(d);

[UnmanagedCallersOnly(EntryPoint = "__call_reducer__")]
public static short __call_reducer__(
public static SpacetimeDB.Internal.Errno __call_reducer__(
uint id,
ulong sender_0,
ulong sender_1,
Expand Down
2 changes: 2 additions & 0 deletions modules/benchmarks-cs/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
bin
obj
3 changes: 3 additions & 0 deletions modules/benchmarks-cs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
This C# source code is manually derived from `../benchmarks/src/` and is supposed to be functionally equivalent.

Do not add new types or functionality here that is not present in the Rust version, because they're compared against each other.
22 changes: 22 additions & 0 deletions modules/benchmarks-cs/StdbModule.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<RuntimeIdentifier>wasi-wasm</RuntimeIdentifier>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<!-- ignore naming conventions, we're trying to match Rust 1:1 -->
<NoWarn>$(NoWarn);CS8981;IDE1006</NoWarn>
</PropertyGroup>

<!--
Use local package sources instead of published ones.
This makes integration test somewhat differ from production configuration, but
at least it simplifies workflow for editing and testing C# code itself.
-->
<ItemGroup>
<ProjectReference Include="../../crates/bindings-csharp/Codegen/Codegen.csproj" OutputItemType="Analyzer" />
<ProjectReference Include="../../crates/bindings-csharp/Runtime/Runtime.csproj" />
</ItemGroup>

</Project>
151 changes: 151 additions & 0 deletions modules/benchmarks-cs/circles.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@

using SpacetimeDB;

namespace Benchmarks;
public static partial class circles
{
[SpacetimeDB.Type]
public partial struct Vector2(float x, float y)
{
public float x = x;
public float y = y;
}

[SpacetimeDB.Table]
public partial struct Entity(uint id, float x, float y, uint mass)
{
[SpacetimeDB.Column(ColumnAttrs.PrimaryKeyAuto)]
public uint id = id;
public Vector2 position = new(x, y);
public uint mass = mass;
}

[SpacetimeDB.Table]
public partial struct Circle(uint entity_id, uint player_id, float x, float y, float magnitude)
{
[SpacetimeDB.Column(ColumnAttrs.PrimaryKey)]
public uint entity_id = entity_id;

[SpacetimeDB.Column(ColumnAttrs.Indexed)]
public uint player_id = player_id;

public Vector2 direction = new(x, y);
public float magnitude = magnitude;
public ulong last_split_time = (ulong)(DateTimeOffset.UtcNow.Ticks / 10);
}

[SpacetimeDB.Table]
public partial struct Food(uint entity_id)
{
[SpacetimeDB.Column(ColumnAttrs.PrimaryKey)]
public uint entity_id = entity_id;
}

public static float MassToRadius(uint mass)
{
return (float)Math.Sqrt(mass);
}

public static bool IsOverlapping(Entity entity1, Entity entity2)
{
float entity1_radius = MassToRadius(entity1.mass);
float entity2_radius = MassToRadius(entity2.mass);
float distance = (float)
Math.Sqrt(
Math.Pow(entity1.position.x - entity2.position.x, 2)
+ Math.Pow(entity1.position.y - entity2.position.y, 2)
);
return distance < Math.Max(entity1_radius, entity2_radius);
}

[SpacetimeDB.Reducer]
public static void insert_bulk_entity(uint count)
{
for (uint id = 0; id < count; id++)
{
new Entity(0, id, id + 5, id * 5).Insert();
}
Runtime.Log($"INSERT ENTITY: {count}");
}

[SpacetimeDB.Reducer]
public static void insert_bulk_circle(uint count)
{
for (uint id = 0; id < count; id++)
{
new Circle(id, id, id, id + 5, id * 5).Insert();
}
Runtime.Log($"INSERT CIRCLE: {count}");
}

[SpacetimeDB.Reducer]
public static void insert_bulk_food(uint count)
{
for (uint id = 1; id <= count; id++)
{
new Food(id).Insert();
}
Runtime.Log($"INSERT FOOD: {count}");
}

[SpacetimeDB.Reducer]
public static void cross_join_all(uint expected)
{
uint count = 0;
foreach (Circle circle in Circle.Iter())
{
foreach (Entity entity in Entity.Iter())
{
foreach (Food food in Food.Iter())
{
count++;
}
}
}

Runtime.Log($"CROSS JOIN ALL: {expected}, processed: {count}");
}

[SpacetimeDB.Reducer]
public static void cross_join_circle_food(uint expected)
{
uint count = 0;
foreach (Circle circle in Circle.Iter())
{
if (Entity.FindByid(circle.entity_id) is not { } circle_entity)
{
continue;
}

foreach (Food food in Food.Iter())
{
count++;
Entity food_entity =
Entity.FindByid(food.entity_id)
?? throw new Exception($"Entity not found: {food.entity_id}");
Bench.BlackBox(IsOverlapping(circle_entity, food_entity));
}
}

Runtime.Log($"CROSS JOIN CIRCLE FOOD: {expected}, processed: {count}");
}

[SpacetimeDB.Reducer]
public static void init_game_circles(uint initial_load)
{
Load load = new(initial_load);

insert_bulk_food(load.initial_load);
insert_bulk_entity(load.initial_load);
insert_bulk_circle(load.small_table);
}

[SpacetimeDB.Reducer]
public static void run_game_circles(uint initial_load)
{
Load load = new(initial_load);

cross_join_circle_food(initial_load * load.small_table);
cross_join_all(initial_load * initial_load * load.small_table);
}
}
Loading
Loading