Skip to content

Commit

Permalink
C# module benchmarks (#1679)
Browse files Browse the repository at this point in the history
  • Loading branch information
RReverser authored Sep 6, 2024
1 parent df5ef6c commit 2cccac4
Show file tree
Hide file tree
Showing 13 changed files with 1,107 additions and 10 deletions.
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

2 comments on commit 2cccac4

@github-actions
Copy link

@github-actions github-actions bot commented on 2cccac4 Sep 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Benchmarking failed. Please check the workflow run for details.

@github-actions
Copy link

@github-actions github-actions bot commented on 2cccac4 Sep 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Benchmarking failed. Please check the workflow run for details.

Please sign in to comment.