mirror of
https://github.com/esiur/esiur-dotnet.git
synced 2026-04-29 06:48:41 +00:00
up
This commit is contained in:
@@ -10,6 +10,7 @@ using Esiur.Resource;
|
|||||||
using Microsoft.CodeAnalysis;
|
using Microsoft.CodeAnalysis;
|
||||||
using Microsoft.CodeAnalysis.CSharp;
|
using Microsoft.CodeAnalysis.CSharp;
|
||||||
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
||||||
|
using Org.BouncyCastle.Asn1.Cms;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
@@ -75,29 +76,70 @@ namespace Esiur.Proxy
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var code = @$"using Esiur.Resource;
|
var code = new StringBuilder();
|
||||||
using Esiur.Core;
|
|
||||||
|
|
||||||
#nullable enable
|
var ns = ci.ClassSymbol.ContainingNamespace.ToDisplayString();
|
||||||
|
if (ns == null || ns == "<global namespace>")
|
||||||
|
{
|
||||||
|
|
||||||
namespace {ci.ClassSymbol.ContainingNamespace.ToDisplayString()} {{
|
}
|
||||||
";
|
|
||||||
|
code.AppendLine("using Esiur.Resource;");
|
||||||
|
code.AppendLine("using Esiur.Core;");
|
||||||
|
code.AppendLine("#nullable enable");
|
||||||
|
|
||||||
|
if (!(ns == null || ns == "<global namespace>"))
|
||||||
|
{
|
||||||
|
code.AppendLine($"namespace {ns};");
|
||||||
|
}
|
||||||
|
|
||||||
|
code.AppendLine();
|
||||||
|
code.AppendLine($"// <auto-generated> DO NOT EDIT THIS FILE! </auto-generated>");
|
||||||
|
code.AppendLine($"// This file was generated by {nameof(ResourceGenerator)} based on the presence of [Resource] and [Export] attributes in {ci.ClassSymbol.Name}.cs");
|
||||||
|
|
||||||
if (IsInterfaceImplemented(ci, classes))
|
if (IsInterfaceImplemented(ci, classes))
|
||||||
code += $"public partial class {ci.Name} {{\r\n";
|
{
|
||||||
|
code.AppendLine($"public partial class {ci.Name}");
|
||||||
|
code.AppendLine("{");
|
||||||
|
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
code +=
|
code.AppendLine($"public partial class {ci.Name} : IResource");
|
||||||
$@" public partial class {ci.Name} : IResource {{
|
code.AppendLine("{");
|
||||||
public virtual Instance? Instance {{ get; set; }}
|
code.AppendLine("public virtual Instance? Instance { get; set; }");
|
||||||
public virtual event DestroyedEvent? OnDestroy;
|
code.AppendLine("public virtual event DestroyedEvent? OnDestroy;");
|
||||||
|
code.AppendLine("public virtual void Destroy() { OnDestroy?.Invoke(this); }");
|
||||||
public virtual void Destroy() {{ OnDestroy?.Invoke(this); }}
|
|
||||||
";
|
|
||||||
|
|
||||||
if (!ci.HasTrigger)
|
if (!ci.HasTrigger)
|
||||||
code += "\tpublic virtual AsyncReply<bool> Trigger(ResourceTrigger trigger) => new AsyncReply<bool>(true);\r\n\r\n";
|
{
|
||||||
|
code.AppendLine("public virtual AsyncReply<bool> Trigger(ResourceTrigger trigger) => new AsyncReply<bool>(true);");
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// var code = @$"using Esiur.Resource;
|
||||||
|
//using Esiur.Core;
|
||||||
|
|
||||||
|
//#nullable enable
|
||||||
|
|
||||||
|
//namespace {ci.ClassSymbol.ContainingNamespace.ToDisplayString()} {{
|
||||||
|
//";
|
||||||
|
|
||||||
|
// if (IsInterfaceImplemented(ci, classes))
|
||||||
|
// code += $"public partial class {ci.Name} {{\r\n";
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// code +=
|
||||||
|
//$@" public partial class {ci.Name} : IResource {{
|
||||||
|
// public virtual Instance? Instance {{ get; set; }}
|
||||||
|
// public virtual event DestroyedEvent? OnDestroy;
|
||||||
|
|
||||||
|
// public virtual void Destroy() {{ OnDestroy?.Invoke(this); }}
|
||||||
|
//";
|
||||||
|
|
||||||
|
// if (!ci.HasTrigger)
|
||||||
|
// code += "\tpublic virtual AsyncReply<bool> Trigger(ResourceTrigger trigger) => new AsyncReply<bool>(true);\r\n\r\n";
|
||||||
|
// }
|
||||||
|
|
||||||
foreach (var f in ci.Fields)
|
foreach (var f in ci.Fields)
|
||||||
{
|
{
|
||||||
@@ -106,21 +148,26 @@ $@" public partial class {ci.Name} : IResource {{
|
|||||||
var fn = f.Name;
|
var fn = f.Name;
|
||||||
var pn = string.IsNullOrEmpty(givenName) ? SuggestExportName(fn) : givenName;
|
var pn = string.IsNullOrEmpty(givenName) ? SuggestExportName(fn) : givenName;
|
||||||
|
|
||||||
var attrs = string.Join("\r\n\t", f.GetAttributes().Select(x => FormatAttribute(x)));
|
var attrs = f.GetAttributes().Select(x => FormatAttribute(x));
|
||||||
|
|
||||||
|
foreach(var attr in attrs)
|
||||||
|
code.AppendLine($"\t{attr}");
|
||||||
|
|
||||||
|
|
||||||
if (f.Type.Name.StartsWith("ResourceEventHandler") || f.Type.Name.StartsWith("CustomResourceEventHandler"))
|
if (f.Type.Name.StartsWith("ResourceEventHandler") || f.Type.Name.StartsWith("CustomResourceEventHandler"))
|
||||||
{
|
{
|
||||||
code += $"\t{attrs}\r\n\t public event {f.Type} {pn};\r\n";
|
code.AppendLine($"public event {f.Type} {pn};");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
code += $"\t{attrs}\r\n\t public {f.Type} {pn} {{ \r\n\t\t get => {fn}; \r\n\t\t set {{ \r\n\t\t this.{fn} = value; \r\n\t\t Instance?.Modified(); \r\n\t\t}}\r\n\t}}\r\n";
|
code.AppendLine($"\t{attrs}\r\n\t public {f.Type} {pn} {{ \r\n\t\t get => {fn}; \r\n\t\t set {{ \r\n\t\t this.{fn} = value; \r\n\t\t Instance?.Modified(); \r\n\t\t}}\r\n\t}}\r\n");
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
code += "}}\r\n";
|
code.AppendLine("}\r\n");
|
||||||
|
|
||||||
spc.AddSource(ci.Name + ".g.cs", code);
|
spc.AddSource(ci.Name + ".g.cs", code.ToString());
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -7,4 +7,8 @@
|
|||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\..\..\Libraries\Esiur\Esiur.csproj" OutputItemType="Analyzer" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
using Esiur.Resource;
|
using Esiur.Resource;
|
||||||
using Esiur.Stores;
|
using Esiur.Stores;
|
||||||
using Esiur.Net.IIP;
|
using Esiur.Protocol;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
|
||||||
var mode = GetArg(args, "--mode", "both");
|
var mode = GetArg(args, "--mode", "both");
|
||||||
@@ -29,28 +29,30 @@ var concurrent = int.Parse(GetArg(args, "--concurrent", "50"));
|
|||||||
var resources = int.Parse(GetArg(args, "--resources", "200"));
|
var resources = int.Parse(GetArg(args, "--resources", "200"));
|
||||||
var timeoutMs = int.Parse(GetArg(args, "--timeout", "10000"));
|
var timeoutMs = int.Parse(GetArg(args, "--timeout", "10000"));
|
||||||
var rounds = int.Parse(GetArg(args, "--rounds", "5"));
|
var rounds = int.Parse(GetArg(args, "--rounds", "5"));
|
||||||
|
var wh = new Warehouse();
|
||||||
|
|
||||||
// ----------------------------------------------------------------
|
// ----------------------------------------------------------------
|
||||||
// SERVER SIDE
|
// SERVER SIDE
|
||||||
// ----------------------------------------------------------------
|
// ----------------------------------------------------------------
|
||||||
if (mode == "server" || mode == "both")
|
if (mode == "server" || mode == "both")
|
||||||
{
|
{
|
||||||
await Warehouse.Put("sys", new MemoryStore());
|
|
||||||
await Warehouse.Put("sys/server", new DistributedServer() { Port = (ushort)port });
|
await wh.Put("sys", new MemoryStore());
|
||||||
|
await wh.Put("sys/server", new EpServer() { Port = (ushort)port });
|
||||||
|
|
||||||
for (int i = 0; i < resources; i++)
|
for (int i = 0; i < resources; i++)
|
||||||
{
|
{
|
||||||
await Warehouse.Put($"sys/sensor_{i}", new SensorResource { SensorId = i, Value = i });
|
await wh.Put($"sys/sensor_{i}", new SensorResource { SensorId = i, Value = i });
|
||||||
}
|
}
|
||||||
|
|
||||||
await Warehouse.Open();
|
await wh.Open();
|
||||||
Console.WriteLine($"[Server-T3] Ready: {resources} resources on port {port}");
|
Console.WriteLine($"[Server-T3] Ready: {resources} resources on port {port}");
|
||||||
|
|
||||||
if (mode == "server")
|
if (mode == "server")
|
||||||
{
|
{
|
||||||
Console.WriteLine("Press ENTER to stop.");
|
Console.WriteLine("Press ENTER to stop.");
|
||||||
Console.ReadLine();
|
Console.ReadLine();
|
||||||
await Warehouse.Close();
|
await wh.Close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,7 +90,7 @@ for (int round = 0; round < rounds; round++)
|
|||||||
using var cts = new CancellationTokenSource(timeoutMs);
|
using var cts = new CancellationTokenSource(timeoutMs);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var proxy = await Warehouse.Get<IResource>(
|
var proxy = await wh.Get<IResource>(
|
||||||
$"iip://{host}:{port}/sys/sensor_{resourceIdx}");
|
$"iip://{host}:{port}/sys/sensor_{resourceIdx}");
|
||||||
|
|
||||||
sw.Stop();
|
sw.Stop();
|
||||||
@@ -160,7 +162,7 @@ await File.WriteAllTextAsync("test3_concurrent_attach.csv", csv);
|
|||||||
Console.WriteLine("\n[Client-T3] Results written to test3_concurrent_attach.csv");
|
Console.WriteLine("\n[Client-T3] Results written to test3_concurrent_attach.csv");
|
||||||
|
|
||||||
if (mode == "both")
|
if (mode == "both")
|
||||||
await Warehouse.Close();
|
await wh.Close();
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------
|
// ----------------------------------------------------------------
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
using Esiur.Resource;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Shared observable sensor resource used across all scalability tests.
|
||||||
|
/// Property changes via Value setter are automatically propagated
|
||||||
|
/// to all attached remote peers by the Esiur runtime.
|
||||||
|
/// </summary>
|
||||||
|
[Resource]
|
||||||
|
public partial class SensorResource : Resource
|
||||||
|
{
|
||||||
|
public int SensorId { get; set; }
|
||||||
|
|
||||||
|
[Export]
|
||||||
|
public double value;
|
||||||
|
}
|
||||||
@@ -7,4 +7,8 @@
|
|||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\..\..\Libraries\Esiur\Esiur.csproj" OutputItemType="Analyzer" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -17,9 +17,9 @@
|
|||||||
// Usage (client only): dotnet run -- --mode client --host 127.0.0.1 --concurrent 50 --resources 200
|
// Usage (client only): dotnet run -- --mode client --host 127.0.0.1 --concurrent 50 --resources 200
|
||||||
// ============================================================
|
// ============================================================
|
||||||
|
|
||||||
|
using Esiur.Protocol;
|
||||||
using Esiur.Resource;
|
using Esiur.Resource;
|
||||||
using Esiur.Stores;
|
using Esiur.Stores;
|
||||||
using Esiur.Net.IIP;
|
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
|
||||||
var mode = GetArg(args, "--mode", "both");
|
var mode = GetArg(args, "--mode", "both");
|
||||||
@@ -30,27 +30,28 @@ var resources = int.Parse(GetArg(args, "--resources", "200"));
|
|||||||
var timeoutMs = int.Parse(GetArg(args, "--timeout", "10000"));
|
var timeoutMs = int.Parse(GetArg(args, "--timeout", "10000"));
|
||||||
var rounds = int.Parse(GetArg(args, "--rounds", "5"));
|
var rounds = int.Parse(GetArg(args, "--rounds", "5"));
|
||||||
|
|
||||||
|
var wh = new Warehouse();
|
||||||
// ----------------------------------------------------------------
|
// ----------------------------------------------------------------
|
||||||
// SERVER SIDE
|
// SERVER SIDE
|
||||||
// ----------------------------------------------------------------
|
// ----------------------------------------------------------------
|
||||||
if (mode == "server" || mode == "both")
|
if (mode == "server" || mode == "both")
|
||||||
{
|
{
|
||||||
await Warehouse.Put("sys", new MemoryStore());
|
await wh.Put("sys", new MemoryStore());
|
||||||
await Warehouse.Put("sys/server", new DistributedServer() { Port = (ushort)port });
|
await wh.Put("sys/server", new EpServer() { Port = (ushort)port });
|
||||||
|
|
||||||
for (int i = 0; i < resources; i++)
|
for (int i = 0; i < resources; i++)
|
||||||
{
|
{
|
||||||
await Warehouse.Put($"sys/sensor_{i}", new SensorResource { SensorId = i, Value = i });
|
await wh.Put($"sys/sensor_{i}", new SensorResource { SensorId = i, Value = i });
|
||||||
}
|
}
|
||||||
|
|
||||||
await Warehouse.Open();
|
await wh.Open();
|
||||||
Console.WriteLine($"[Server-T3] Ready: {resources} resources on port {port}");
|
Console.WriteLine($"[Server-T3] Ready: {resources} resources on port {port}");
|
||||||
|
|
||||||
if (mode == "server")
|
if (mode == "server")
|
||||||
{
|
{
|
||||||
Console.WriteLine("Press ENTER to stop.");
|
Console.WriteLine("Press ENTER to stop.");
|
||||||
Console.ReadLine();
|
Console.ReadLine();
|
||||||
await Warehouse.Close();
|
await wh.Close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,7 +89,7 @@ for (int round = 0; round < rounds; round++)
|
|||||||
using var cts = new CancellationTokenSource(timeoutMs);
|
using var cts = new CancellationTokenSource(timeoutMs);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var proxy = await Warehouse.Get<IResource>(
|
var proxy = await wh.Get<IResource>(
|
||||||
$"iip://{host}:{port}/sys/sensor_{resourceIdx}");
|
$"iip://{host}:{port}/sys/sensor_{resourceIdx}");
|
||||||
|
|
||||||
sw.Stop();
|
sw.Stop();
|
||||||
@@ -160,7 +161,7 @@ await File.WriteAllTextAsync("test3_concurrent_attach.csv", csv);
|
|||||||
Console.WriteLine("\n[Client-T3] Results written to test3_concurrent_attach.csv");
|
Console.WriteLine("\n[Client-T3] Results written to test3_concurrent_attach.csv");
|
||||||
|
|
||||||
if (mode == "both")
|
if (mode == "both")
|
||||||
await Warehouse.Close();
|
await wh.Close();
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------
|
// ----------------------------------------------------------------
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
using Esiur.Resource;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Shared observable sensor resource used across all scalability tests.
|
||||||
|
/// Property changes via Value setter are automatically propagated
|
||||||
|
/// to all attached remote peers by the Esiur runtime.
|
||||||
|
/// </summary>
|
||||||
|
[Resource]
|
||||||
|
public partial class SensorResource : Resource
|
||||||
|
{
|
||||||
|
public int SensorId { get; set; }
|
||||||
|
|
||||||
|
[Export]
|
||||||
|
public double value;
|
||||||
|
}
|
||||||
@@ -7,4 +7,8 @@
|
|||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\..\..\Libraries\Esiur\Esiur.csproj" OutputItemType="Analyzer"/>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -32,11 +32,13 @@ var latencyLock = new object();
|
|||||||
var proxies = new dynamic[resourceCount];
|
var proxies = new dynamic[resourceCount];
|
||||||
var sw = Stopwatch.StartNew();
|
var sw = Stopwatch.StartNew();
|
||||||
|
|
||||||
|
var wh = new Warehouse();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
for (int i = 0; i < resourceCount; i++)
|
for (int i = 0; i < resourceCount; i++)
|
||||||
{
|
{
|
||||||
proxies[i] = await Warehouse.Get<IResource>($"iip://{host}:{port}/sys/sensor_{i}");
|
proxies[i] = await wh.Get<IResource>($"iip://{host}:{port}/sys/sensor_{i}");
|
||||||
|
|
||||||
// Subscribe to property change notifications via the Esiur event model
|
// Subscribe to property change notifications via the Esiur event model
|
||||||
double lastValue = (double)proxies[i].Value;
|
double lastValue = (double)proxies[i].Value;
|
||||||
|
|||||||
@@ -7,4 +7,8 @@
|
|||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\..\..\Libraries\Esiur\Esiur.csproj" OutputItemType="Analyzer"/>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -9,8 +9,8 @@
|
|||||||
|
|
||||||
using Esiur.Resource;
|
using Esiur.Resource;
|
||||||
using Esiur.Stores;
|
using Esiur.Stores;
|
||||||
using Esiur.Net.IIP;
|
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using Esiur.Protocol;
|
||||||
|
|
||||||
var resourceCount = int.Parse(GetArg(args, "--resources", "100"));
|
var resourceCount = int.Parse(GetArg(args, "--resources", "100"));
|
||||||
var intervalMs = int.Parse(GetArg(args, "--interval", "50"));
|
var intervalMs = int.Parse(GetArg(args, "--interval", "50"));
|
||||||
@@ -18,19 +18,20 @@ var port = int.Parse(GetArg(args, "--port", "10900"));
|
|||||||
|
|
||||||
Console.WriteLine($"[Server] resources={resourceCount} interval={intervalMs}ms port={port}");
|
Console.WriteLine($"[Server] resources={resourceCount} interval={intervalMs}ms port={port}");
|
||||||
|
|
||||||
|
var wh = new Warehouse();
|
||||||
// --- Warehouse setup -------------------------------------------------
|
// --- Warehouse setup -------------------------------------------------
|
||||||
await Warehouse.Put("sys", new MemoryStore());
|
await wh.Put("sys", new MemoryStore());
|
||||||
await Warehouse.Put("sys/server", new DistributedServer() { Port = (ushort)port });
|
await wh.Put("sys/server", new EpServer() { Port = (ushort)port });
|
||||||
|
|
||||||
// Create and register all sensor resources
|
// Create and register all sensor resources
|
||||||
var sensors = new SensorResource[resourceCount];
|
var sensors = new SensorResource[resourceCount];
|
||||||
for (int i = 0; i < resourceCount; i++)
|
for (int i = 0; i < resourceCount; i++)
|
||||||
{
|
{
|
||||||
sensors[i] = new SensorResource { SensorId = i };
|
sensors[i] = new SensorResource { SensorId = i };
|
||||||
await Warehouse.Put($"sys/sensor_{i}", sensors[i]);
|
await wh.Put($"sys/sensor_{i}", sensors[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
await Warehouse.Open();
|
await wh.Open();
|
||||||
Console.WriteLine($"[Server] Listening on port {port} with {resourceCount} resources.");
|
Console.WriteLine($"[Server] Listening on port {port} with {resourceCount} resources.");
|
||||||
|
|
||||||
// --- Emit loop -------------------------------------------------------
|
// --- Emit loop -------------------------------------------------------
|
||||||
@@ -68,7 +69,7 @@ _ = Task.Run(async () =>
|
|||||||
|
|
||||||
Console.WriteLine("Press ENTER to stop.");
|
Console.WriteLine("Press ENTER to stop.");
|
||||||
Console.ReadLine();
|
Console.ReadLine();
|
||||||
await Warehouse.Close();
|
await wh.Close();
|
||||||
|
|
||||||
|
|
||||||
// --- Helpers ---------------------------------------------------------
|
// --- Helpers ---------------------------------------------------------
|
||||||
|
|||||||
@@ -1,24 +1,15 @@
|
|||||||
using Esiur.Resource;
|
using Esiur.Resource;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A simple observable sensor resource.
|
/// Shared observable sensor resource used across all scalability tests.
|
||||||
/// Property changes are automatically propagated to all attached peers.
|
/// Property changes via Value setter are automatically propagated
|
||||||
|
/// to all attached remote peers by the Esiur runtime.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Resource]
|
[Resource]
|
||||||
public class SensorResource : Resource
|
public partial class SensorResource : Resource
|
||||||
{
|
{
|
||||||
public int SensorId { get; set; }
|
public int SensorId { get; set; }
|
||||||
|
|
||||||
private double _value;
|
[Export]
|
||||||
|
public double value;
|
||||||
[ResourceProperty]
|
|
||||||
public double Value
|
|
||||||
{
|
|
||||||
get => _value;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_value = value;
|
|
||||||
PropertyModified("Value"); // notifies Esiur runtime to propagate
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,4 +7,8 @@
|
|||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\..\..\Libraries\Esiur\Esiur.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ var proxies = new dynamic[resourceCount];
|
|||||||
|
|
||||||
// --- Attach in batches to avoid overwhelming the runtime -------------
|
// --- Attach in batches to avoid overwhelming the runtime -------------
|
||||||
var totalSw = Stopwatch.StartNew();
|
var totalSw = Stopwatch.StartNew();
|
||||||
|
var wh = new Warehouse();
|
||||||
for (int batch = 0; batch < resourceCount; batch += batchSize)
|
for (int batch = 0; batch < resourceCount; batch += batchSize)
|
||||||
{
|
{
|
||||||
int end = Math.Min(batch + batchSize, resourceCount);
|
int end = Math.Min(batch + batchSize, resourceCount);
|
||||||
@@ -35,7 +35,7 @@ for (int batch = 0; batch < resourceCount; batch += batchSize)
|
|||||||
batchTasks[i - batch] = Task.Run(async () =>
|
batchTasks[i - batch] = Task.Run(async () =>
|
||||||
{
|
{
|
||||||
var sw = Stopwatch.StartNew();
|
var sw = Stopwatch.StartNew();
|
||||||
proxies[capturedI] = await Warehouse.Get<IResource>(
|
proxies[capturedI] = await wh.Get<IResource>(
|
||||||
$"iip://{host}:{port}/sys/sensor_{capturedI}");
|
$"iip://{host}:{port}/sys/sensor_{capturedI}");
|
||||||
sw.Stop();
|
sw.Stop();
|
||||||
|
|
||||||
|
|||||||
@@ -7,4 +7,8 @@
|
|||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\..\..\Libraries\Esiur\Esiur.csproj" OutputItemType="Analyzer"/>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -8,25 +8,27 @@
|
|||||||
|
|
||||||
using Esiur.Resource;
|
using Esiur.Resource;
|
||||||
using Esiur.Stores;
|
using Esiur.Stores;
|
||||||
using Esiur.Net.IIP;
|
using Esiur.Protocol;
|
||||||
|
|
||||||
var resourceCount = int.Parse(GetArg(args, "--resources", "10000"));
|
var resourceCount = int.Parse(GetArg(args, "--resources", "10000"));
|
||||||
var port = int.Parse(GetArg(args, "--port", "10901"));
|
var port = int.Parse(GetArg(args, "--port", "10901"));
|
||||||
|
|
||||||
Console.WriteLine($"[Server-T2] Creating {resourceCount} resources on port {port}");
|
Console.WriteLine($"[Server-T2] Creating {resourceCount} resources on port {port}");
|
||||||
|
|
||||||
await Warehouse.Put("sys", new MemoryStore());
|
var wh = new Warehouse();
|
||||||
await Warehouse.Put("sys/server", new DistributedServer() { Port = (ushort)port });
|
|
||||||
|
await wh.Put("sys", new MemoryStore());
|
||||||
|
await wh.Put("sys/server", new EpServer() { Port = (ushort)port });
|
||||||
|
|
||||||
long memBefore = GC.GetTotalMemory(forceFullCollection: true);
|
long memBefore = GC.GetTotalMemory(forceFullCollection: true);
|
||||||
|
|
||||||
for (int i = 0; i < resourceCount; i++)
|
for (int i = 0; i < resourceCount; i++)
|
||||||
{
|
{
|
||||||
var s = new SensorResource { SensorId = i, Value = i * 0.1 };
|
var s = new SensorResource { SensorId = i, Value = i * 0.1 };
|
||||||
await Warehouse.Put($"sys/sensor_{i}", s);
|
await wh.Put($"sys/sensor_{i}", s);
|
||||||
}
|
}
|
||||||
|
|
||||||
await Warehouse.Open();
|
await wh.Open();
|
||||||
|
|
||||||
long memAfter = GC.GetTotalMemory(forceFullCollection: true);
|
long memAfter = GC.GetTotalMemory(forceFullCollection: true);
|
||||||
double memMB = (memAfter - memBefore) / (1024.0 * 1024.0);
|
double memMB = (memAfter - memBefore) / (1024.0 * 1024.0);
|
||||||
@@ -35,7 +37,7 @@ Console.WriteLine($"[Server-T2] Ready. Resources={resourceCount} MemoryUsed={me
|
|||||||
Console.WriteLine($"[Server-T2] Per-resource ≈ {(memAfter - memBefore) / (double)resourceCount:F0} bytes");
|
Console.WriteLine($"[Server-T2] Per-resource ≈ {(memAfter - memBefore) / (double)resourceCount:F0} bytes");
|
||||||
Console.WriteLine("Press ENTER to stop.");
|
Console.WriteLine("Press ENTER to stop.");
|
||||||
Console.ReadLine();
|
Console.ReadLine();
|
||||||
await Warehouse.Close();
|
await wh.Close();
|
||||||
|
|
||||||
|
|
||||||
static string GetArg(string[] args, string key, string def)
|
static string GetArg(string[] args, string key, string def)
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
using Esiur.Resource;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Shared observable sensor resource used across all scalability tests.
|
||||||
|
/// Property changes via Value setter are automatically propagated
|
||||||
|
/// to all attached remote peers by the Esiur runtime.
|
||||||
|
/// </summary>
|
||||||
|
[Resource]
|
||||||
|
public partial class SensorResource : Resource
|
||||||
|
{
|
||||||
|
public int SensorId { get; set; }
|
||||||
|
|
||||||
|
[Export]
|
||||||
|
public double value;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user