Files
ssh.net/test/Renci.SshNet.IntegrationBenchmarks/SshClientBenchmark.cs
T
Rob Hague fdbc4d3e36 Fix a few issues with PipeStream (#1399)
Apply similar treatment to PipeStream as #1322 did to ShellStream

PipeStream now behaves much more Stream-like. In particular, it performs partial
reads (instead of blocking until a certain amount of data is available), blocks
until data is available (instead of returning 0 prematurely) and removes the
Stream-unlike properties `BlockLastReadBuffer` and `MaxBufferLength`.

Sadly I gave up trying to make a benchmark compatible with all the quirks of the
previous implementation, but a dumb throughput test (reading and writing simultaneously)
shows about 5.2GB/s with this implementation compared to 140MB/s previously.

Some cleanup of its usage in the library followed.

Co-authored-by: Wojciech Nagórski <wojtpl2@gmail.com>
2024-05-23 15:30:05 +02:00

117 lines
4.4 KiB
C#

using BenchmarkDotNet.Attributes;
using Renci.SshNet.Common;
using Renci.SshNet.IntegrationTests.TestsFixtures;
namespace Renci.SshNet.IntegrationBenchmarks
{
[MemoryDiagnoser]
[SimpleJob]
public class SshClientBenchmark : IntegrationBenchmarkBase
{
private static readonly Dictionary<TerminalModes, uint> ShellStreamTerminalModes = new Dictionary<TerminalModes, uint>
{
{ TerminalModes.ECHO, 0 }
};
private readonly InfrastructureFixture _infrastructureFixture;
private SshClient? _sshClient;
public SshClientBenchmark()
{
_infrastructureFixture = InfrastructureFixture.Instance;
}
[GlobalSetup]
public async Task Setup()
{
await GlobalSetup().ConfigureAwait(false);
_sshClient = new SshClient(_infrastructureFixture.SshServerHostName, _infrastructureFixture.SshServerPort, _infrastructureFixture.User.UserName, _infrastructureFixture.User.Password);
await _sshClient.ConnectAsync(CancellationToken.None).ConfigureAwait(false);
}
[GlobalCleanup]
public async Task Cleanup()
{
await GlobalCleanup().ConfigureAwait(false);
}
[Benchmark]
public void Connect()
{
using var sshClient = new SshClient(_infrastructureFixture.SshServerHostName, _infrastructureFixture.SshServerPort, _infrastructureFixture.User.UserName, _infrastructureFixture.User.Password);
sshClient.Connect();
}
[Benchmark]
public async Task ConnectAsync()
{
using var sshClient = new SshClient(_infrastructureFixture.SshServerHostName, _infrastructureFixture.SshServerPort, _infrastructureFixture.User.UserName, _infrastructureFixture.User.Password);
await sshClient.ConnectAsync(CancellationToken.None).ConfigureAwait(false);
}
[Benchmark]
public string ConnectAndRunCommand()
{
using var sshClient = new SshClient(_infrastructureFixture.SshServerHostName, _infrastructureFixture.SshServerPort, _infrastructureFixture.User.UserName, _infrastructureFixture.User.Password);
sshClient.Connect();
return sshClient.RunCommand("echo $'test !@#$%^&*()_+{}:,./<>[];\\|'").Result;
}
[Benchmark]
public async Task<string> ConnectAsyncAndRunCommand()
{
using var sshClient = new SshClient(_infrastructureFixture.SshServerHostName, _infrastructureFixture.SshServerPort, _infrastructureFixture.User.UserName, _infrastructureFixture.User.Password);
await sshClient.ConnectAsync(CancellationToken.None).ConfigureAwait(false);
return sshClient.RunCommand("echo $'test !@#$%^&*()_+{}:,./<>[];\\|'").Result;
}
[Benchmark]
public string RunCommand()
{
return _sshClient!.RunCommand("echo $'test !@#$%^&*()_+{}:,./<>[];\\|'").Result;
}
[Benchmark]
public string RunBigCommand()
{
using var command = _sshClient!.CreateCommand("head -c 10000000 /dev/urandom | base64"); // 10MB of data please
var asyncResult = command.BeginExecute();
command.OutputStream.CopyTo(Stream.Null);
return command.EndExecute(asyncResult);
}
[Benchmark]
public string ShellStreamReadLine()
{
using (var shellStream = _sshClient!.CreateShellStream("xterm", 80, 24, 800, 600, 1024, ShellStreamTerminalModes))
{
shellStream.WriteLine("for i in $(seq 500); do echo \"Within cells. Interlinked. $i\"; sleep 0.001; done; echo \"Username:\";");
while (true)
{
var line = shellStream.ReadLine()!;
if (line.EndsWith("500", StringComparison.Ordinal))
{
return line;
}
}
}
}
[Benchmark]
public string? ShellStreamExpect()
{
using (var shellStream = _sshClient!.CreateShellStream("xterm", 80, 24, 800, 600, 1024, ShellStreamTerminalModes))
{
shellStream.WriteLine("for i in $(seq 500); do echo \"Within cells. Interlinked. $i\"; sleep 0.001; done; echo \"Username:\";");
return shellStream.Expect("Username:");
}
}
}
}