Skip to content

Commit 14e5098

Browse files
SteveGibsonCLSteve BoytsunRReverser
authored
Stopwatch and reducer rng (#1681)
Signed-off-by: Ingvar Stepanyan <me@rreverser.com> Co-authored-by: Steve Boytsun <steve@clockwokrlabs.io> Co-authored-by: Ingvar Stepanyan <me@rreverser.com>
1 parent f6bc6dc commit 14e5098

File tree

11 files changed

+100
-22
lines changed

11 files changed

+100
-22
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ __pycache__/
202202
cs-src/
203203
crates/bench/spacetime.svg
204204
crates/bench/sqlite.svg
205+
.vs/
205206

206207
# benchmark files
207208
out.json

crates/bindings-csharp/Runtime/Exceptions.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,11 @@ public class NoSuchIterException : StdbException
4242
public override string Message => "The provided row iterator does not exist";
4343
}
4444

45+
public class NoSuchLogStopwatch : StdbException
46+
{
47+
public override string Message => "The provided stopwatch does not exist";
48+
}
49+
4550
public class NoSuchBytesException : StdbException
4651
{
4752
public override string Message => "The provided bytes source or sink does not exist";

crates/bindings-csharp/Runtime/Internal/FFI.cs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ public enum Errno : short
2727
BSATN_DECODE_ERROR = 3,
2828
NO_SUCH_TABLE = 4,
2929
NO_SUCH_ITER = 6,
30+
NO_SUCH_CONSOLE_TIMER = 7,
3031
NO_SUCH_BYTES = 8,
3132
NO_SPACE = 9,
3233
BUFFER_TOO_SMALL = 11,
@@ -75,6 +76,7 @@ public static CheckedStatus ConvertToManaged(Errno status)
7576
Errno.BSATN_DECODE_ERROR => new BsatnDecodeException(),
7677
Errno.NO_SUCH_TABLE => new NoSuchTableException(),
7778
Errno.NO_SUCH_ITER => new NoSuchIterException(),
79+
Errno.NO_SUCH_CONSOLE_TIMER => new NoSuchLogStopwatch(),
7880
Errno.NO_SUCH_BYTES => new NoSuchBytesException(),
7981
Errno.NO_SPACE => new NoSpaceException(),
8082
Errno.BUFFER_TOO_SMALL => new BufferTooSmallException(),
@@ -221,4 +223,35 @@ public static partial CheckedStatus _bytes_sink_write(
221223
ReadOnlySpan<byte> buffer,
222224
ref uint buffer_len
223225
);
226+
227+
[NativeMarshalling(typeof(ConsoleTimerIdMarshaller))]
228+
[StructLayout(LayoutKind.Sequential)]
229+
public readonly struct ConsoleTimerId
230+
{
231+
private readonly uint timer_id;
232+
233+
private ConsoleTimerId(uint id)
234+
{
235+
timer_id = id;
236+
}
237+
238+
//LayoutKind.Sequential is apparently not enough for this struct to be returnable in PInvoke, so we need a custom marshaller unfortunately
239+
[CustomMarshaller(
240+
typeof(ConsoleTimerId),
241+
MarshalMode.Default,
242+
typeof(ConsoleTimerIdMarshaller)
243+
)]
244+
internal static class ConsoleTimerIdMarshaller
245+
{
246+
public static ConsoleTimerId ConvertToManaged(uint id) => new ConsoleTimerId(id);
247+
248+
public static uint ConvertToUnmanaged(ConsoleTimerId id) => id.timer_id;
249+
}
250+
}
251+
252+
[LibraryImport(StdbNamespace)]
253+
public static partial ConsoleTimerId _console_timer_start([In] byte[] name, uint name_len);
254+
255+
[LibraryImport(StdbNamespace)]
256+
public static partial CheckedStatus _console_timer_end(ConsoleTimerId stopwatch_id);
224257
}

crates/bindings-csharp/Runtime/Internal/Module.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -192,11 +192,10 @@ BytesSink error
192192

193193
try
194194
{
195-
Runtime.Random = new((int)timestamp.MicrosecondsSinceEpoch);
196-
197195
using var stream = new MemoryStream(args.Consume());
198196
using var reader = new BinaryReader(stream);
199-
reducers[(int)id].Invoke(reader, new(sender, address, timestamp.ToStd()));
197+
var context = new ReducerContext(sender, address, timestamp);
198+
reducers[(int)id].Invoke(reader, context);
200199
if (stream.Position != stream.Length)
201200
{
202201
throw new Exception("Unrecognised extra bytes in the reducer arguments");
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
using System.Text;
2+
using SpacetimeDB.Internal;
3+
4+
namespace SpacetimeDB;
5+
6+
public sealed class LogStopwatch : IDisposable
7+
{
8+
private readonly FFI.ConsoleTimerId StopwatchId;
9+
private bool WasStopped;
10+
11+
public LogStopwatch(string name)
12+
{
13+
var name_bytes = Encoding.UTF8.GetBytes(name);
14+
StopwatchId = FFI._console_timer_start(name_bytes, (uint)name_bytes.Length);
15+
}
16+
17+
void IDisposable.Dispose()
18+
{
19+
if (!WasStopped)
20+
{
21+
End();
22+
}
23+
}
24+
25+
public void End()
26+
{
27+
FFI._console_timer_end(StopwatchId);
28+
WasStopped = true;
29+
}
30+
}

crates/bindings-csharp/Runtime/Runtime.cs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,21 @@ public class ReducerContext
1111
public readonly DateTimeOffset Time;
1212
public readonly Address? Address;
1313

14+
/// <summary>
15+
/// A reducer-specific instance of `System.Random` that is seeded by current reducer's timestamp. This object is unchanged throught the entire reducer call
16+
/// </summary>
17+
public readonly Random Rng;
18+
1419
internal ReducerContext(
1520
Identity senderIdentity,
1621
Address? senderAddress,
17-
DateTimeOffset timestamp
22+
DateTimeOffsetRepr timestamp
1823
)
1924
{
2025
Sender = senderIdentity;
2126
Address = senderAddress;
22-
Time = timestamp;
27+
Time = timestamp.ToStd();
28+
Rng = new Random((int)timestamp.MicrosecondsSinceEpoch);
2329
}
2430
}
2531

@@ -112,7 +118,4 @@ public static void Log(
112118
(uint)text_bytes.Length
113119
);
114120
}
115-
116-
// An instance of `System.Random` that is reseeded by each reducer's timestamp.
117-
public static Random Random { get; internal set; } = new();
118121
}

crates/bindings-csharp/Runtime/bindings.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ OPAQUE_TYPEDEF(LogLevel, uint8_t);
2121
OPAQUE_TYPEDEF(BytesSink, uint32_t);
2222
OPAQUE_TYPEDEF(BytesSource, uint32_t);
2323
OPAQUE_TYPEDEF(RowIter, uint32_t);
24+
OPAQUE_TYPEDEF(ConsoleTimerId, uint32_t);
2425

2526
#define CSTR(s) (uint8_t*)s, sizeof(s) - 1
2627

@@ -79,6 +80,12 @@ IMPORT(int16_t, _bytes_source_read, (BytesSource source, uint8_t* buffer_ptr, si
7980
(source, buffer_ptr, buffer_len_ptr));
8081
IMPORT(uint16_t, _bytes_sink_write, (BytesSink sink, const uint8_t* buffer_ptr, size_t* buffer_len_ptr),
8182
(sink, buffer_ptr, buffer_len_ptr));
83+
IMPORT(ConsoleTimerId, _console_timer_start,
84+
(const uint8_t* name, size_t name_len),
85+
(name, name_len));
86+
IMPORT(Status, _console_timer_end,
87+
(ConsoleTimerId stopwatch_id),
88+
(stopwatch_id));
8289

8390
#ifndef EXPERIMENTAL_WASM_AOT
8491
static MonoClass* ffi_class;

crates/bindings/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,12 @@
44
#[macro_use]
55
mod io;
66
mod impls;
7+
pub mod log_stopwatch;
78
mod logger;
89
#[cfg(feature = "rand")]
910
mod rng;
1011
#[doc(hidden)]
1112
pub mod rt;
12-
pub mod time_span;
1313
mod timestamp;
1414

1515
use spacetimedb_lib::buffer::{BufReader, BufWriter, Cursor, DecodeError};
Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
1-
pub struct Span {
2-
span_id: u32,
1+
pub struct LogStopwatch {
2+
stopwatch_id: u32,
33
}
44

5-
impl Span {
6-
pub fn start(name: &str) -> Self {
5+
impl LogStopwatch {
6+
pub fn new(name: &str) -> Self {
77
let name = name.as_bytes();
88
let id = unsafe { spacetimedb_bindings_sys::raw::_console_timer_start(name.as_ptr(), name.len()) };
9-
Self { span_id: id }
9+
Self { stopwatch_id: id }
1010
}
1111

1212
pub fn end(self) {
1313
// just drop self
1414
}
1515
}
1616

17-
impl std::ops::Drop for Span {
17+
impl std::ops::Drop for LogStopwatch {
1818
fn drop(&mut self) {
1919
unsafe {
20-
spacetimedb_bindings_sys::raw::_console_timer_end(self.span_id);
20+
spacetimedb_bindings_sys::raw::_console_timer_end(self.stopwatch_id);
2121
}
2222
}
2323
}

crates/primitives/src/errno.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ macro_rules! errnos {
1414
NO_SUCH_TABLE(4, "No such table"),
1515
NO_SUCH_INDEX(5, "No such index"),
1616
NO_SUCH_ITER(6, "The provided row iterator is not valid"),
17-
NO_SUCH_CONSOLE_TIMER(7, "The started console timer does not exist"),
17+
NO_SUCH_CONSOLE_TIMER(7, "The provided console timer does not exist"),
1818
NO_SUCH_BYTES(8, "The provided bytes source or sink is not valid"),
1919
NO_SPACE(9, "The provided sink has no more space left"),
2020
BUFFER_TOO_SMALL(11, "The provided buffer is not large enough to store the data"),

0 commit comments

Comments
 (0)