-
Notifications
You must be signed in to change notification settings - Fork 58
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
Support all binary payload APIs with only generics #143
Merged
Merged
Changes from 5 commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
11e07f0
API serializer proposal
mtmk ad780d6
Nested NATS default serializer
mtmk aaa9410
Fixed perf test
mtmk f235506
Micro benchmarks tidy up
mtmk cf285c2
Removed string serializer
mtmk 4709d2d
Rename publishing and empty payload
mtmk f17b4e5
Revert pub sentinel naming
mtmk 5129358
Merge branch 'main' into support-bytes-apis-via-generics
mtmk 882f993
Fixed test
mtmk File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,169 @@ | ||
#pragma warning disable IDE0044 | ||
using System.Text.Json; | ||
using BenchmarkDotNet.Attributes; | ||
using Microsoft.Extensions.DependencyInjection; | ||
using Microsoft.Extensions.Logging; | ||
using NATS.Client.Core; | ||
using StackExchange.Redis; | ||
using ZLogger; | ||
|
||
namespace MicroBenchmark; | ||
|
||
public struct MyVector3 | ||
{ | ||
public float X { get; set; } | ||
|
||
public float Y { get; set; } | ||
|
||
public float Z { get; set; } | ||
} | ||
|
||
// var run = new DefaultRun(); | ||
// await run.SetupAsync(); | ||
// await run.RunBenchmark(); | ||
// await run.RunStackExchangeRedis(); | ||
|
||
// await run.CleanupAsync(); | ||
#pragma warning disable CS8618 | ||
|
||
[MemoryDiagnoser] | ||
[ShortRunJob] | ||
[PlainExporter] | ||
public class DefaultBench | ||
{ | ||
#pragma warning disable CS8618 // Non-nullable field must contain a non-null value when exiting constructor. Consider declaring as nullable. | ||
private NatsConnection _connection; | ||
private string _subject; | ||
private ConnectionMultiplexer _redis; | ||
private object _gate; | ||
private Handler _handler; | ||
private IDisposable _subscription = default!; | ||
|
||
[GlobalSetup] | ||
public async Task SetupAsync() | ||
{ | ||
var provider = new ServiceCollection() | ||
.AddLogging(x => | ||
{ | ||
x.ClearProviders(); | ||
x.SetMinimumLevel(LogLevel.Information); | ||
x.AddZLoggerConsole(); | ||
}) | ||
.BuildServiceProvider(); | ||
|
||
var loggerFactory = provider.GetRequiredService<ILoggerFactory>(); | ||
var logger = loggerFactory.CreateLogger<ILogger<DefaultBench>>(); | ||
var options = NatsOpts.Default with | ||
{ | ||
LoggerFactory = loggerFactory, | ||
Echo = true, | ||
Verbose = false, | ||
}; | ||
|
||
_connection = new NATS.Client.Core.NatsConnection(options); | ||
_subject = "foobar"; | ||
await _connection.ConnectAsync(); | ||
_gate = new object(); | ||
_redis = StackExchange.Redis.ConnectionMultiplexer.Connect("localhost"); | ||
|
||
_handler = new Handler(); | ||
|
||
// subscription = connection.Subscribe<MyVector3>(key, handler.Handle); | ||
} | ||
|
||
// [Benchmark] | ||
public async Task Nop() | ||
{ | ||
await Task.Yield(); | ||
} | ||
|
||
[Benchmark] | ||
public async Task PublishAsync() | ||
{ | ||
for (var i = 0; i < 1; i++) | ||
{ | ||
await _connection.PublishAsync(_subject, default(MyVector3)); | ||
} | ||
} | ||
|
||
// [Benchmark] | ||
public async Task PublishAsyncRedis() | ||
{ | ||
for (var i = 0; i < 1; i++) | ||
{ | ||
await _redis.GetDatabase().PublishAsync(_subject, JsonSerializer.Serialize(default(MyVector3))); | ||
} | ||
} | ||
|
||
// [Benchmark] | ||
public void RunBenchmark() | ||
{ | ||
const int count = 10000; | ||
_handler.Gate = _gate; | ||
_handler.Called = 0; | ||
_handler.Max = count; | ||
|
||
for (var i = 0; i < count; i++) | ||
{ | ||
_connection.PublishAsync(_subject, default(MyVector3)); | ||
} | ||
|
||
lock (_gate) | ||
{ | ||
// Monitor.Wait(gate); | ||
Thread.Sleep(1000); | ||
} | ||
} | ||
|
||
// [Benchmark] | ||
// public async Task RunStackExchangeRedis() | ||
// { | ||
// var tcs = new TaskCompletionSource(); | ||
// var called = 0; | ||
// redis.GetSubscriber().Subscribe(key.Key, (channel, v) => | ||
// { | ||
// if (Interlocked.Increment(ref called) == 1000) | ||
// { | ||
// tcs.TrySetResult(); | ||
// } | ||
// }); | ||
|
||
// for (int i = 0; i < 1000; i++) | ||
// { | ||
// _ = redis.GetDatabase().PublishAsync(key.Key, JsonSerializer.Serialize(new MyVector3()), StackExchange.Redis.CommandFlags.FireAndForget); | ||
// } | ||
|
||
// await tcs.Task; | ||
// } | ||
[GlobalCleanup] | ||
public async Task CleanupAsync() | ||
{ | ||
_subscription?.Dispose(); | ||
if (_connection != null) | ||
{ | ||
await _connection.DisposeAsync(); | ||
} | ||
|
||
_redis?.Dispose(); | ||
} | ||
|
||
private class Handler | ||
{ | ||
#pragma warning disable SA1401 | ||
public int Called; | ||
public int Max; | ||
public object Gate; | ||
#pragma warning restore SA1401 | ||
|
||
public void Handle(MyVector3 vec) | ||
{ | ||
if (Interlocked.Increment(ref Called) == Max) | ||
{ | ||
lock (Gate) | ||
{ | ||
Monitor.PulseAll(Gate); | ||
} | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is the null-forgiving operator needed here? Is
SubscribeAsync<T>
eventually returningT?
instead? Would be nice if we could avoid thatThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Default values in general yield empty/sentinel payloads that's why there are
T?
s in a lot of places. Do you think we shouldn't allow nulls? How would we handle sending and receiving empty payloads?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True, I guess there is no way to avoid it for reference types when
default
may be retruned. Seeing as System.Text.JSON even does it