Skip to content

Commit 20fba89

Browse files
authored
doc(Modbus): add Benchmark result (#6753)
* doc: 更新 Socket 转实体类文档 * doc: 增加 Benchmark 结果 * doc: 更新基准测试文档 * doc: 更新错别字 * doc: 增加读写数据阈值文档
1 parent c198c04 commit 20fba89

File tree

2 files changed

+71
-2
lines changed

2 files changed

+71
-2
lines changed

src/BootstrapBlazor.Server/Components/Samples/Modbus/ModbusFactories.razor

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,3 +68,68 @@ private IModbusFactory? ModbusFactory { get; set; }</Pre>
6868
<li>输入寄存器 (Input Registers) <code>ReadInputRegistersAsync</code></li>
6969
<li>保持寄存器 (Holding Registers) <code>ReadHoldingRegistersAsync</code> <code>WriteRegisterAsync</code> <code>WriteMultipleRegistersAsync</code></li>
7070
</ul>
71+
72+
<p>Modbus 协议的最大读取/写入数量限制参考自 Modbus Application Protocol Specification V1.1b3:</p>
73+
74+
<ul class="ul-demo">
75+
<li>线圈 (Coils) 最大读取数量: <code>2000</code>, 最大写入数量: <code>1968</code></li>
76+
<li>离散输入 (Discrete Inputs) 最大读取数量: <code>2000</code></li>
77+
<li>输入寄存器 (Input Registers) 最大读取数量: <code>125</code></li>
78+
<li>保持寄存器 (Holding Registers) 最大读取数量: <code>125</code>, 最大写入数量: <code>123</code></li>
79+
</ul>
80+
81+
<p>项目包含 Benchmark 基准测试工程</p>
82+
83+
<Pre>private const int NumberOfTask = 10;
84+
private const int TaskNumberOfClient = 10;
85+
private const int ClientCount = 10;
86+
87+
private async Task InitLongbowModbus()
88+
{
89+
var sc = new ServiceCollection();
90+
sc.AddModbusFactory();
91+
92+
var provider = sc.BuildServiceProvider();
93+
var factory = provider.GetRequiredService&lt;IModbusFactory&gt;();
94+
95+
for (var index = 0; index &lt; ClientCount; index++)
96+
{
97+
var client = factory.GetOrCreateTcpMaster();
98+
await client.ConnectAsync("127.0.0.1", 502);
99+
await client.ReadHoldingRegistersAsync(0x01, 0x00, 100);
100+
101+
_lgbModbusClients.Add(client);
102+
}
103+
}
104+
105+
[Benchmark]
106+
public async Task LongbowModbus()
107+
{
108+
var tasks = _lgbModbusClients.SelectMany(c =>
109+
{
110+
var tasks = new List&lt;Task&gt;();
111+
for (int i = 0; i &lt; TaskNumberOfClient; i++)
112+
{
113+
tasks.Add(Task.Run(async () =&gt;
114+
{
115+
for (int i = 0; i &lt; NumberOfTask; i++)
116+
{
117+
var d = await c.ReadHoldingRegistersAsync(1, 0, 100);
118+
}
119+
}));
120+
}
121+
return tasks;
122+
}).ToList();
123+
124+
await Task.WhenAll(tasks);
125+
}</Pre>
126+
127+
<p>共 10 个 <code>Socket</code> 连接,每个连接 10 个并发任务,每个任务进行 10 次 <code>ReadHoldingRegistersAsync</code> 方法调用,每个方法读取 100 个地址数据</p>
128+
129+
<p>Benchmark 结果如下:</p>
130+
131+
<Pre>| Method | Mean | Error | StdDev | Allocated |
132+
|------------------ |--------:|---------:|---------:|----------:|
133+
| LongbowModbus | 2.458 s | 0.0488 s | 0.1007 s | 2.11 MB |
134+
| NModbus | 4.752 s | 0.1544 s | 0.4552 s | 3.3 MB |
135+
</Pre>

src/BootstrapBlazor.Server/Components/Samples/Sockets/DataEntities.razor

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,12 +75,16 @@
7575
}
7676
}</Pre>
7777
<p>此处返回值会与参数 <code>Type = typeof(Foo)</code> 做数据合规检查,如果返回值无法转换为指定 <code>Type</code> 时不进行赋值操作,代码逻辑如下</p>
78-
<Pre>var attr = p.GetCustomAttribute&lt;DataPropertyConverterAttribute&gt;(false) ?? GetPropertyConverterAttribute(p);
78+
<Pre>var attr = p.GetCustomAttribute&lt;DataPropertyConverterAttribute&gt;(false);
7979
if (attr is { Type: not null })
8080
{
8181
var value = attr.ConvertTo(data);
8282
var valueType = value?.GetType();
83-
if (p.PropertyType.IsAssignableFrom(valueType))
83+
if (value == null && IsNullable(p.PropertyType))
84+
{
85+
p.SetValue(entity, null);
86+
}
87+
else if (p.PropertyType.IsAssignableFrom(valueType))
8488
{
8589
p.SetValue(entity, value);
8690
}

0 commit comments

Comments
 (0)