From 4e5cc532b55a89fe69dba6a4caa4223efa7665c6 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Thu, 5 Sep 2024 16:19:03 +0100 Subject: [PATCH 1/5] WIP C# module benchmarks --- modules/benchmarks-cs/.gitignore | 2 + modules/benchmarks-cs/StdbModule.csproj | 22 ++ modules/benchmarks-cs/circles.cs | 151 +++++++ modules/benchmarks-cs/ia_loop.cs | 372 +++++++++++++++++ modules/benchmarks-cs/lib.cs | 30 ++ modules/benchmarks-cs/synthetic.cs | 504 ++++++++++++++++++++++++ 6 files changed, 1081 insertions(+) create mode 100644 modules/benchmarks-cs/.gitignore create mode 100644 modules/benchmarks-cs/StdbModule.csproj create mode 100644 modules/benchmarks-cs/circles.cs create mode 100644 modules/benchmarks-cs/ia_loop.cs create mode 100644 modules/benchmarks-cs/lib.cs create mode 100644 modules/benchmarks-cs/synthetic.cs diff --git a/modules/benchmarks-cs/.gitignore b/modules/benchmarks-cs/.gitignore new file mode 100644 index 0000000000..1746e3269e --- /dev/null +++ b/modules/benchmarks-cs/.gitignore @@ -0,0 +1,2 @@ +bin +obj diff --git a/modules/benchmarks-cs/StdbModule.csproj b/modules/benchmarks-cs/StdbModule.csproj new file mode 100644 index 0000000000..f821c10d1d --- /dev/null +++ b/modules/benchmarks-cs/StdbModule.csproj @@ -0,0 +1,22 @@ + + + + net8.0 + wasi-wasm + enable + enable + + $(NoWarn);CS8981;IDE1006 + + + + + + + + + diff --git a/modules/benchmarks-cs/circles.cs b/modules/benchmarks-cs/circles.cs new file mode 100644 index 0000000000..cb94f42f9a --- /dev/null +++ b/modules/benchmarks-cs/circles.cs @@ -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); + } +} diff --git a/modules/benchmarks-cs/ia_loop.cs b/modules/benchmarks-cs/ia_loop.cs new file mode 100644 index 0000000000..74e309b16a --- /dev/null +++ b/modules/benchmarks-cs/ia_loop.cs @@ -0,0 +1,372 @@ +using SpacetimeDB; + +namespace Benchmarks; + +public static partial class ia_loop +{ + [SpacetimeDB.Table] + public partial struct Velocity(uint entity_id, float x, float y, float z) + { + [SpacetimeDB.Column(ColumnAttrs.PrimaryKey)] + public uint entity_id = entity_id; + public float x = x; + public float y = y; + public float z = z; + } + + [SpacetimeDB.Table] + public partial struct Position(uint entity_id, float x, float y, float z) + { + [SpacetimeDB.Column(ColumnAttrs.PrimaryKey)] + public uint entity_id = entity_id; + public float x = x; + public float y = y; + public float z = z; + public float vx = x + 10.0f; + public float vy = y + 20.0f; + public float vz = z + 30.0f; + } + + public static ulong MomentMilliseconds() + { + // Idk why Rust uses complicated math, but it seems like it should always return 1. + return 1; + } + + [SpacetimeDB.Type] + public enum AgentAction + { + Inactive, + Idle, + Evading, + Investigating, + Retreating, + Fighting, + } + + [SpacetimeDB.Table] + public partial struct GameEnemyAiAgentState( + ulong entity_id, + List last_move_timestamps, + ulong next_action_timestamp, + AgentAction action + ) + { + [SpacetimeDB.Column(ColumnAttrs.PrimaryKey)] + public ulong entity_id = entity_id; + public List last_move_timestamps = last_move_timestamps; + public ulong next_action_timestamp = next_action_timestamp; + public AgentAction action = action; + } + + [SpacetimeDB.Table] + public partial struct GameTargetableState(ulong entity_id, long quad) + { + [SpacetimeDB.Column(ColumnAttrs.PrimaryKey)] + public ulong entity_id = entity_id; + public long quad = quad; + } + + [SpacetimeDB.Table] + public partial struct GameLiveTargetableState(ulong entity_id, long quad) + { + [SpacetimeDB.Column(ColumnAttrs.Unique)] + public ulong entity_id = entity_id; + + [SpacetimeDB.Column(ColumnAttrs.Indexed)] + public long quad = quad; + } + + [SpacetimeDB.Table] + public partial struct GameMobileEntityState( + ulong entity_id, + int location_x, + int location_y, + ulong timestamp + ) + { + [SpacetimeDB.Column(ColumnAttrs.PrimaryKey)] + public ulong entity_id = entity_id; + + [SpacetimeDB.Column(ColumnAttrs.Indexed)] + public int location_x = location_x; + public int location_y = location_y; + public ulong timestamp = timestamp; + } + + [SpacetimeDB.Table] + public partial struct GameEnemyState(ulong entity_id, int herd_id) + { + [SpacetimeDB.Column(ColumnAttrs.PrimaryKey)] + public ulong entity_id = entity_id; + public int herd_id = herd_id; + } + + [SpacetimeDB.Type] + public partial struct SmallHexTile(int x, int z, uint dimension) + { + public int x = x; + public int z = z; + public uint dimension = dimension; + } + + [SpacetimeDB.Table] + public partial struct GameHerdCache( + int id, + uint dimension_id, + int current_population, + SmallHexTile location, + int max_population, + float spawn_eagerness, + int roaming_distance + ) + { + [SpacetimeDB.Column(ColumnAttrs.PrimaryKey)] + public int id = id; + public uint dimension_id = dimension_id; + public int current_population = current_population; + public SmallHexTile location = location; + public int max_population = max_population; + public float spawn_eagerness = spawn_eagerness; + public int roaming_distance = roaming_distance; + } + + [SpacetimeDB.Reducer] + public static void InsertBulkPosition(uint count) + { + for (uint id = 0; id < count; id++) + { + new Position(id, id, id + 5, id * 5).Insert(); + } + Runtime.Log($"INSERT POSITION: {count}"); + } + + [SpacetimeDB.Reducer] + public static void InsertBulkVelocity(uint count) + { + for (uint id = 0; id < count; id++) + { + new Velocity(id, id, id + 5, id * 5).Insert(); + } + Runtime.Log($"INSERT VELOCITY: {count}"); + } + + [SpacetimeDB.Reducer] + public static void update_position_all(uint expected) + { + uint count = 0; + foreach (Position position in Position.Iter()) + { + Position newPosition = position; + + newPosition.x += position.vx; + newPosition.y += position.vy; + newPosition.z += position.vz; + + Position.UpdateByentity_id(position.entity_id, newPosition); + count++; + } + Runtime.Log($"UPDATE POSITION ALL: {expected}, processed: {count}"); + } + + [SpacetimeDB.Reducer] + public static void update_position_with_velocity(uint expected) + { + uint count = 0; + foreach (Velocity velocity in Velocity.Iter()) + { + if (Position.FindByentity_id(velocity.entity_id) is not { } position) + { + continue; + } + + position.x += velocity.x; + position.y += velocity.y; + position.z += velocity.z; + + Position.UpdateByentity_id(position.entity_id, position); + count++; + } + Runtime.Log($"UPDATE POSITION BY VELOCITY: {expected}, processed: {count}"); + } + + [SpacetimeDB.Reducer] + public static void insert_world(ulong players) + { + for (ulong i = 0; i < players; i++) + { + ulong next_action_timestamp = + (i & 2) == 2 ? MomentMilliseconds() + 2000 : MomentMilliseconds(); + + new GameEnemyAiAgentState( + i, + [i, 0, i * 2], + next_action_timestamp, + AgentAction.Idle + ).Insert(); + + new GameLiveTargetableState(i, (long)i).Insert(); + + new GameTargetableState(i, (long)i).Insert(); + + new GameMobileEntityState(i, (int)i, (int)i, next_action_timestamp).Insert(); + + new GameEnemyState(i, (int)i).Insert(); + + new GameHerdCache( + (int)i, + (uint)i, + (int)(i * 2), + new SmallHexTile((int)i, (int)i, (uint)(i * 2)), + (int)(i * 4), + i, + (int)i + ).Insert(); + } + Runtime.Log($"INSERT WORLD PLAYERS: {players}"); + } + + public static List GetTargetablesNearQuad( + ulong entity_id, + ulong num_players + ) + { + List result = new(4); + + for (ulong id = entity_id; id < num_players; id++) + { + foreach (GameLiveTargetableState t in GameLiveTargetableState.FilterByquad((long)id)) + { + result.Add( + GameTargetableState.FindByentity_id(t.entity_id) + ?? throw new Exception("Identity not found") + ); + } + } + + return result; + } + + private const int MAX_MOVE_TIMESTAMPS = 20; + + public static void MoveAgent( + ref GameEnemyAiAgentState agent, + SmallHexTile agent_coord, + ulong current_time_ms + ) + { + ulong entity_id = agent.entity_id; + + GameEnemyState enemy = + GameEnemyState.FindByentity_id(entity_id) + ?? throw new Exception("GameEnemyState Entity ID not found"); + GameEnemyState.UpdateByentity_id(entity_id, enemy); + + agent.next_action_timestamp = current_time_ms + 2000; + + agent.last_move_timestamps.Add(current_time_ms); + if (agent.last_move_timestamps.Count > MAX_MOVE_TIMESTAMPS) + { + agent.last_move_timestamps.RemoveAt(0); + } + + GameTargetableState targetable = + GameTargetableState.FindByentity_id(entity_id) + ?? throw new Exception("GameTargetableState Entity ID not found"); + int new_hash = targetable.quad.GetHashCode(); + targetable.quad = new_hash; + GameTargetableState.UpdateByentity_id(entity_id, targetable); + + if (GameLiveTargetableState.FindByentity_id(entity_id) is not null) + { + GameLiveTargetableState.UpdateByentity_id(entity_id, new(entity_id, new_hash)); + } + + GameMobileEntityState mobile_entity = + GameMobileEntityState.FindByentity_id(entity_id) + ?? throw new Exception("GameMobileEntityState Entity ID not found"); + mobile_entity.location_x += 1; + mobile_entity.location_y += 1; + mobile_entity.timestamp = MomentMilliseconds(); + + GameEnemyAiAgentState.UpdateByentity_id(entity_id, agent); + + GameMobileEntityState.UpdateByentity_id(entity_id, mobile_entity); + } + + public static void AgentLoop( + GameEnemyAiAgentState agent, + GameTargetableState agent_targetable, + List surrounding_agents, + ulong current_time_ms + ) + { + ulong entity_id = agent.entity_id; + + IEnumerable coordinates = + GameMobileEntityState.FilterByentity_id(entity_id) + ?? throw new Exception("GameMobileEntityState Entity ID not found"); + + GameEnemyState agent_entity = + GameEnemyState.FindByentity_id(entity_id) + ?? throw new Exception("GameEnemyState Entity ID not found"); + + GameHerdCache agent_herd = + GameHerdCache.FindByid(agent_entity.herd_id) + ?? throw new Exception("GameHerdCache Entity ID not found"); + + SmallHexTile agent_herd_coordinates = agent_herd.location; + + MoveAgent(ref agent, agent_herd_coordinates, current_time_ms); + } + + [SpacetimeDB.Reducer] + public static void game_loop_enemy_ia(ulong players) + { + uint count = 0; + ulong current_time_ms = MomentMilliseconds(); + + foreach (GameEnemyAiAgentState agent in GameEnemyAiAgentState.Iter()) + { + if (agent.next_action_timestamp > current_time_ms) + { + continue; + } + + GameTargetableState agent_targetable = + GameTargetableState.FindByentity_id(agent.entity_id) + ?? throw new Exception("No TargetableState for AgentState entity"); + + List surrounding_agents = GetTargetablesNearQuad(agent_targetable.entity_id, players); + + GameEnemyAiAgentState newAgent = agent with { action = AgentAction.Fighting }; + + AgentLoop(newAgent, agent_targetable, surrounding_agents, current_time_ms); + + count++; + } + + Runtime.Log($"ENEMY IA LOOP PLAYERS: {players}, processed: {count}"); + } + + [SpacetimeDB.Reducer] + public static void init_game_ia_loop(uint initial_load) + { + Load load = new(initial_load); + + InsertBulkPosition(load.biggest_table); + InsertBulkVelocity(load.big_table); + update_position_all(load.biggest_table); + update_position_with_velocity(load.big_table); + + insert_world(load.num_players); + } + + [SpacetimeDB.Reducer] + public static void run_game_ia_loop(uint initial_load) + { + Load load = new(initial_load); + + game_loop_enemy_ia(load.num_players); + } +} diff --git a/modules/benchmarks-cs/lib.cs b/modules/benchmarks-cs/lib.cs new file mode 100644 index 0000000000..c72027d57c --- /dev/null +++ b/modules/benchmarks-cs/lib.cs @@ -0,0 +1,30 @@ +using System.Runtime.CompilerServices; + +namespace Benchmarks; + +public static class Bench +{ + public static void BlackBox(IEnumerable input) + { + foreach (T? item in input) + { + BlackBox(item); + } + } + + [MethodImpl(MethodImplOptions.NoInlining)] + public static void BlackBox(T input) + { + _ = input; + } +} + +[SpacetimeDB.Type] +public partial struct Load(uint initial_load) +{ + public uint initial_load = initial_load; + public uint small_table = initial_load; + public uint num_players = initial_load; + public uint big_table = initial_load * 50; + public uint biggest_table = initial_load * 100; +} diff --git a/modules/benchmarks-cs/synthetic.cs b/modules/benchmarks-cs/synthetic.cs new file mode 100644 index 0000000000..4a39ab5617 --- /dev/null +++ b/modules/benchmarks-cs/synthetic.cs @@ -0,0 +1,504 @@ +using SpacetimeDB; + +namespace Benchmarks; + +public static partial class synthetic +{ + // ---------- schemas ---------- + + [SpacetimeDB.Table] + public partial struct unique_0_u32_u64_str + { + [SpacetimeDB.Column(ColumnAttrs.Unique)] + public uint id; + public ulong age; + public string name; + } + + [SpacetimeDB.Table] + public partial struct no_index_u32_u64_str + { + public uint id; + public ulong age; + public string name; + } + + [SpacetimeDB.Table] + public partial struct btree_each_column_u32_u64_str + { + [SpacetimeDB.Column(ColumnAttrs.Indexed)] + public uint id; + + [SpacetimeDB.Column(ColumnAttrs.Indexed)] + public ulong age; + + [SpacetimeDB.Column(ColumnAttrs.Indexed)] + public string name; + } + + [SpacetimeDB.Table] + public partial struct unique_0_u32_u64_u64 + { + [SpacetimeDB.Column(ColumnAttrs.Unique)] + public uint id; + public ulong x; + public ulong y; + } + + [SpacetimeDB.Table] + public partial struct no_index_u32_u64_u64 + { + public uint id; + public ulong x; + public ulong y; + } + + [SpacetimeDB.Table] + public partial struct btree_each_column_u32_u64_u64 + { + [SpacetimeDB.Column(ColumnAttrs.Indexed)] + public uint id; + + [SpacetimeDB.Column(ColumnAttrs.Indexed)] + public ulong x; + + [SpacetimeDB.Column(ColumnAttrs.Indexed)] + public ulong y; + } + + // ---------- empty ---------- + + [SpacetimeDB.Reducer] + public static void empty() { } + + // ---------- insert ---------- + + [SpacetimeDB.Reducer] + public static void insert_unique_0_u32_u64_str(uint id, ulong age, string name) + { + new unique_0_u32_u64_str() + { + id = id, + age = age, + name = name, + }.Insert(); + } + + [SpacetimeDB.Reducer] + public static void insert_no_index_u32_u64_str(uint id, ulong age, string name) + { + new no_index_u32_u64_str() + { + id = id, + age = age, + name = name, + }.Insert(); + } + + [SpacetimeDB.Reducer] + public static void insert_btree_each_column_u32_u64_str(uint id, ulong age, string name) + { + new btree_each_column_u32_u64_str() + { + id = id, + age = age, + name = name, + }.Insert(); + } + + [SpacetimeDB.Reducer] + public static void insert_unique_0_u32_u64_u64(uint id, ulong x, ulong y) + { + new unique_0_u32_u64_u64() + { + id = id, + x = x, + y = y, + }.Insert(); + } + + [SpacetimeDB.Reducer] + public static void insert_no_index_u32_u64_u64(uint id, ulong x, ulong y) + { + new no_index_u32_u64_u64() + { + id = id, + x = x, + y = y, + }.Insert(); + } + + [SpacetimeDB.Reducer] + public static void insert_btree_each_column_u32_u64_u64(uint id, ulong x, ulong y) + { + new btree_each_column_u32_u64_u64() + { + id = id, + x = x, + y = y, + }.Insert(); + } + + // ---------- insert bulk ---------- + + [SpacetimeDB.Reducer] + public static void insert_bulk_unique_0_u32_u64_u64(List locs) + { + foreach (unique_0_u32_u64_u64 loc in locs) + { + loc.Insert(); + } + } + + [SpacetimeDB.Reducer] + public static void insert_bulk_no_index_u32_u64_u64(List locs) + { + foreach (no_index_u32_u64_u64 loc in locs) + { + loc.Insert(); + } + } + + [SpacetimeDB.Reducer] + public static void insert_bulk_btree_each_column_u32_u64_u64( + List locs + ) + { + foreach (btree_each_column_u32_u64_u64 loc in locs) + { + loc.Insert(); + } + } + + [SpacetimeDB.Reducer] + public static void insert_bulk_unique_0_u32_u64_str(List people) + { + foreach (unique_0_u32_u64_str u32_u64_str in people) + { + u32_u64_str.Insert(); + } + } + + [SpacetimeDB.Reducer] + public static void insert_bulk_no_index_u32_u64_str(List people) + { + foreach (no_index_u32_u64_str u32_u64_str in people) + { + u32_u64_str.Insert(); + } + } + + [SpacetimeDB.Reducer] + public static void insert_bulk_btree_each_column_u32_u64_str( + List people + ) + { + foreach (btree_each_column_u32_u64_str u32_u64_str in people) + { + u32_u64_str.Insert(); + } + } + + // ---------- update ---------- + + [SpacetimeDB.Reducer] + public static void update_bulk_unique_0_u32_u64_u64(uint rowCount) + { + int hit = 0; + foreach (unique_0_u32_u64_u64 loc in unique_0_u32_u64_u64.Iter().Take((int)rowCount)) + { + hit++; + unique_0_u32_u64_u64.UpdateByid( + loc.id, + new() + { + id = loc.id, + x = loc.x + 1, + y = loc.y, + } + ); + } + if (hit != rowCount) + { + throw new Exception("Not enough rows to perform requested amount of updates"); + } + } + + [SpacetimeDB.Reducer] + public static void update_bulk_unique_0_u32_u64_str(uint rowCount) + { + uint hit = 0; + foreach ( + unique_0_u32_u64_str u32_u64_str in unique_0_u32_u64_str.Iter().Take((int)rowCount) + ) + { + hit++; + unique_0_u32_u64_str.UpdateByid( + u32_u64_str.id, + new() + { + id = u32_u64_str.id, + name = u32_u64_str.name, + age = u32_u64_str.age + 1, + } + ); + } + if (hit != rowCount) + { + throw new Exception("Not enough rows to perform requested amount of updates"); + } + } + + // ---------- iterate ---------- + + [SpacetimeDB.Reducer] + public static void iterate_unique_0_u32_u64_str() + { + foreach (unique_0_u32_u64_str u32_u64_str in unique_0_u32_u64_str.Iter()) + { + Bench.BlackBox(u32_u64_str); + } + } + + [SpacetimeDB.Reducer] + public static void iterate_unique_0_u32_u64_u64() + { + foreach (unique_0_u32_u64_u64 u32_u64_u64 in unique_0_u32_u64_u64.Iter()) + { + Bench.BlackBox(u32_u64_u64); + } + } + + // ---------- filtering ---------- + + [SpacetimeDB.Reducer] + public static void filter_unique_0_u32_u64_str_by_id(uint id) + { + Bench.BlackBox(unique_0_u32_u64_str.FindByid(id)); + } + + [SpacetimeDB.Reducer] + public static void filter_no_index_u32_u64_str_by_id(uint id) + { + Bench.BlackBox(no_index_u32_u64_str.FilterByid(id)); + } + + [SpacetimeDB.Reducer] + public static void filter_btree_each_column_u32_u64_str_by_id(uint id) + { + Bench.BlackBox(btree_each_column_u32_u64_str.FilterByid(id)); + } + + [SpacetimeDB.Reducer] + public static void filter_unique_0_u32_u64_str_by_name(string name) + { + Bench.BlackBox(unique_0_u32_u64_str.FilterByname(name)); + } + + [SpacetimeDB.Reducer] + public static void filter_no_index_u32_u64_str_by_name(string name) + { + Bench.BlackBox(no_index_u32_u64_str.FilterByname(name)); + } + + [SpacetimeDB.Reducer] + public static void filter_btree_each_column_u32_u64_str_by_name(string name) + { + Bench.BlackBox(btree_each_column_u32_u64_str.FilterByname(name)); + } + + [SpacetimeDB.Reducer] + public static void filter_unique_0_u32_u64_u64_by_id(uint id) + { + Bench.BlackBox(unique_0_u32_u64_u64.FindByid(id)); + } + + [SpacetimeDB.Reducer] + public static void filter_no_index_u32_u64_u64_by_id(uint id) + { + Bench.BlackBox(no_index_u32_u64_u64.FilterByid(id)); + } + + [SpacetimeDB.Reducer] + public static void filter_btree_each_column_u32_u64_u64_by_id(uint id) + { + Bench.BlackBox(btree_each_column_u32_u64_u64.FilterByid(id)); + } + + [SpacetimeDB.Reducer] + public static void filter_unique_0_u32_u64_u64_by_x(ulong x) + { + Bench.BlackBox(unique_0_u32_u64_u64.FilterByx(x)); + } + + [SpacetimeDB.Reducer] + public static void filter_no_index_u32_u64_u64_by_x(ulong x) + { + Bench.BlackBox(no_index_u32_u64_u64.FilterByx(x)); + } + + [SpacetimeDB.Reducer] + public static void filter_btree_each_column_u32_u64_u64_by_x(ulong x) + { + Bench.BlackBox(btree_each_column_u32_u64_u64.FilterByx(x)); + } + + [SpacetimeDB.Reducer] + public static void filter_unique_0_u32_u64_u64_by_y(ulong x) + { + Bench.BlackBox(unique_0_u32_u64_u64.FilterByy(x)); + } + + [SpacetimeDB.Reducer] + public static void filter_no_index_u32_u64_u64_by_y(ulong x) + { + Bench.BlackBox(no_index_u32_u64_u64.FilterByy(x)); + } + + [SpacetimeDB.Reducer] + public static void filter_btree_each_column_u32_u64_u64_by_y(ulong x) + { + Bench.BlackBox(btree_each_column_u32_u64_u64.FilterByy(x)); + } + + // ---------- delete ---------- + + [SpacetimeDB.Reducer] + public static void delete_unique_0_u32_u64_str_by_id(uint id) + { + unique_0_u32_u64_str.DeleteByid(id); + } + + [SpacetimeDB.Reducer] + public static void delete_unique_0_u32_u64_u64_by_id(uint id) + { + unique_0_u32_u64_u64.DeleteByid(id); + } + + // ---------- clear table ---------- + + [SpacetimeDB.Reducer] + public static void clear_table_unique_0_u32_u64_str() + { + throw new NotImplementedException("Modules currently have no interface to clear a table"); + } + + [SpacetimeDB.Reducer] + public static void clear_table_no_index_u32_u64_str() + { + throw new NotImplementedException("Modules currently have no interface to clear a table"); + } + + [SpacetimeDB.Reducer] + public static void clear_table_btree_each_column_u32_u64_str() + { + throw new NotImplementedException("Modules currently have no interface to clear a table"); + } + + [SpacetimeDB.Reducer] + public static void clear_table_unique_0_u32_u64_u64() + { + throw new NotImplementedException("Modules currently have no interface to clear a table"); + } + + [SpacetimeDB.Reducer] + public static void clear_table_no_index_u32_u64_u64() + { + throw new NotImplementedException("Modules currently have no interface to clear a table"); + } + + [SpacetimeDB.Reducer] + public static void clear_table_btree_each_column_u32_u64_u64() + { + throw new NotImplementedException("Modules currently have no interface to clear a table"); + } + + // ---------- count ---------- + + [SpacetimeDB.Reducer] + public static void count_unique_0_u32_u64_str() + { + Runtime.Log("COUNT: " + unique_0_u32_u64_str.Iter().Count()); + } + + [SpacetimeDB.Reducer] + public static void count_no_index_u32_u64_str() + { + Runtime.Log("COUNT: " + no_index_u32_u64_str.Iter().Count()); + } + + [SpacetimeDB.Reducer] + public static void count_btree_each_column_u32_u64_str() + { + Runtime.Log("COUNT: " + btree_each_column_u32_u64_str.Iter().Count()); + } + + [SpacetimeDB.Reducer] + public static void count_unique_0_u32_u64_u64() + { + Runtime.Log("COUNT: " + unique_0_u32_u64_u64.Iter().Count()); + } + + [SpacetimeDB.Reducer] + public static void count_no_index_u32_u64_u64() + { + Runtime.Log("COUNT: " + no_index_u32_u64_u64.Iter().Count()); + } + + [SpacetimeDB.Reducer] + public static void count_btree_each_column_u32_u64_u64() + { + Runtime.Log("COUNT: " + btree_each_column_u32_u64_u64.Iter().Count()); + } + + // ---------- module-specific stuff ---------- + + [SpacetimeDB.Reducer] + public static void fn_with_1_args(string arg) { } + + [SpacetimeDB.Reducer] + public static void fn_with_32_args( + string arg1, + string arg2, + string arg3, + string arg4, + string arg5, + string arg6, + string arg7, + string arg8, + string arg9, + string arg10, + string arg11, + string arg12, + string arg13, + string arg14, + string arg15, + string arg16, + string arg17, + string arg18, + string arg19, + string arg20, + string arg21, + string arg22, + string arg23, + string arg24, + string arg25, + string arg26, + string arg27, + string arg28, + string arg29, + string arg30, + string arg31, + string arg32 + ) + { } + + [SpacetimeDB.Reducer] + public static void print_many_things(uint n) + { + for (int i = 0; i < n; i++) + { + Runtime.Log("hello again!"); + } + } +} From ee99ba5d620ef742bce87e0915dc8e52d520f9e0 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Thu, 5 Sep 2024 19:25:52 +0100 Subject: [PATCH 2/5] Add env variable to control benchmarks --- crates/bench/src/spacetime_module.rs | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/crates/bench/src/spacetime_module.rs b/crates/bench/src/spacetime_module.rs index da5f11561f..7629a4560c 100644 --- a/crates/bench/src/spacetime_module.rs +++ b/crates/bench/src/spacetime_module.rs @@ -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 + } }; } From 1521cef84a6158ea045c8035965ca57a56f86991 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Fri, 6 Sep 2024 11:22:06 +0100 Subject: [PATCH 3/5] Fixup C# AOT --- crates/bindings-csharp/Codegen/Module.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bindings-csharp/Codegen/Module.cs b/crates/bindings-csharp/Codegen/Module.cs index d1a7acb41f..ffc0f384a7 100644 --- a/crates/bindings-csharp/Codegen/Module.cs +++ b/crates/bindings-csharp/Codegen/Module.cs @@ -445,7 +445,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, From b7c55151f025ad1e6d9847486b48a276b25593f3 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Fri, 6 Sep 2024 11:55:08 +0100 Subject: [PATCH 4/5] Update snapshots --- .../fixtures/server/snapshots/Module#FFI.verified.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#FFI.verified.cs b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#FFI.verified.cs index ee774d9d83..8eab83621e 100644 --- a/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#FFI.verified.cs +++ b/crates/bindings-csharp/Codegen.Tests/fixtures/server/snapshots/Module#FFI.verified.cs @@ -142,7 +142,7 @@ 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, From a183fec35677f2f7b2e12bb57c9ad6e8324385c8 Mon Sep 17 00:00:00 2001 From: Ingvar Stepanyan Date: Fri, 6 Sep 2024 18:42:58 +0100 Subject: [PATCH 5/5] Add README notes to C# modules --- modules/benchmarks-cs/README.md | 3 +++ modules/sdk-test-connect-disconnect-cs/README.md | 3 +++ modules/sdk-test-cs/README.md | 3 +++ modules/spacetimedb-quickstart-cs/README.md | 3 +++ 4 files changed, 12 insertions(+) create mode 100644 modules/benchmarks-cs/README.md create mode 100644 modules/sdk-test-connect-disconnect-cs/README.md create mode 100644 modules/sdk-test-cs/README.md create mode 100644 modules/spacetimedb-quickstart-cs/README.md diff --git a/modules/benchmarks-cs/README.md b/modules/benchmarks-cs/README.md new file mode 100644 index 0000000000..a927335bd3 --- /dev/null +++ b/modules/benchmarks-cs/README.md @@ -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. diff --git a/modules/sdk-test-connect-disconnect-cs/README.md b/modules/sdk-test-connect-disconnect-cs/README.md new file mode 100644 index 0000000000..fff94dde76 --- /dev/null +++ b/modules/sdk-test-connect-disconnect-cs/README.md @@ -0,0 +1,3 @@ +This C# source code is manually derived from `../sdk-test-connect-disconnect/src/lib.rs` 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. diff --git a/modules/sdk-test-cs/README.md b/modules/sdk-test-cs/README.md new file mode 100644 index 0000000000..bac1c25e7e --- /dev/null +++ b/modules/sdk-test-cs/README.md @@ -0,0 +1,3 @@ +This C# source code is manually derived from `../sdk-test/src/lib.rs` 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. diff --git a/modules/spacetimedb-quickstart-cs/README.md b/modules/spacetimedb-quickstart-cs/README.md new file mode 100644 index 0000000000..d92b98074a --- /dev/null +++ b/modules/spacetimedb-quickstart-cs/README.md @@ -0,0 +1,3 @@ +This C# source code is manually derived from `../spacetimedb-quickstart/src/lib.rs` 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.