This project is read-only.

Low performance (Upload time comparing)

Sep 1, 2011 at 10:24 AM

Hi,

I compared upload time of the same file (204Mb) to the same box (Win2008, OpenSSH) using different libs and utilities. The results are the following:

sftpc.exe (http://www.bitvise.com/tunnelier) - 20 min

Enhanced SharpSSH (http://ketulpatel.wordpress.com/2010/05/13/enhanced-sharpssh/) - 30 min

Renci.SshNet - 44 min

Is there a way for SshNet performance improvement?

Thanks,
Anatoli 

Sep 1, 2011 at 11:39 AM

yes,

I am always trying to improve perfomance.

I had it tuned a while back but I guess after many new features something somewhere went wrong.

 

I will take a look at it when I am back from vacation and have some time off from another project.

Meanwhile, can you log it as an issue so I know to get back to it.

 

Thanks,

Oleg

Sep 1, 2011 at 3:16 PM

Done

Oct 19, 2011 at 4:04 PM
Edited Oct 19, 2011 at 4:14 PM

Hi,

Thanks for this nice library. I've been measuring the performance on the SshClient. Comparing it with a commercial library I get about 50% worse performance. My test code looks like this:

PasswordConnectionInfo connectionInfo = new PasswordConnectionInfo("10.100.11.125", 22, "user", "pass");
connectionInfo.Timeout = TimeSpan.FromMilliseconds(5000);
SshClient sshClient = new SshClient(connectionInfo);
sshClient.Connect();
DateTime start = DateTime.Now;
foreach (string command in File.ReadAllLines(@"c:\temp\commands.txt"))
{
    SshCommand result = sshClient.RunCommand(command + "\n");
    Console.Write(result.Result);
}
Console.WriteLine((DateTime.Now - start).TotalMilliseconds);

 Is there anything I can do in the test code to improve the performance?

I'm using SSH.NET 3.5 2011.09.28 connecting to an OpenSsh server. 

 Regards // Magnus


Oct 19, 2011 at 5:39 PM

I actually never done any performance tuning for RunCommand so I guess would be interesting in tuning it up if possible.

Few things about your test:

Can you post the commands that you executing?

Also, if command are environment specific then can we use something like "echo" or other common command?

I will try to improve it as soon as I have a free time from other project.

Thanks,

Oleg

Oct 20, 2011 at 6:43 AM

Oleg,

Thank you for the fast response.

The commands are environment specific. I replaced them with 20 lines of "echo testing" and ran the test again. It took 2275ms with SSH.NET. The same set of commands took 51ms with the commercial library. I would suspect the Nagle-algorithm, but I can see in your code that you've already disabled it.

Regards // Magnus

Oct 20, 2011 at 12:43 PM

Hi,

 

Something I just thought about,

when you do your testing, please check what encryption method do you use.

I noticed significant changes when changing different encryption method.

I suspect thats might be it and commercial libraries probably put it in differnt priorety list, if so I guess I would need to do the same.

 

Thanks,

Oleg

Oct 21, 2011 at 7:16 AM

Hi,

I hope this is the information you want:

ServerVersion = "SSH-2.0-OpenSSH_5.0"

_clientCipher = {Renci.SshNet.Security.Cryptography.Ciphers.TripleDesCipher}

_clientMac = {Renci.SshNet.Security.Cryptography.HMac<Renci.SshNet.Security.Cryptography.MD5Hash>}

_serverCipher = {Renci.SshNet.Security.Cryptography.Ciphers.TripleDesCipher}

_serverMac = {Renci.SshNet.Security.Cryptography.HMac<Renci.SshNet.Security.Cryptography.MD5Hash>}

Regards // Magnus

Oct 26, 2011 at 1:53 PM

Hi,

 

Well, it looks like client uses 3des algorithm for encryption/decryption.

When you do test with other clients do you use 3des algorithm as well or something else?

From what I remember, 3des much slower then aes128 for example.

Nov 1, 2011 at 10:34 AM

Hi Oleg,

Sorry for the late response. The other client uses Aes128. I also tried to force SSH.NET not to use 3des by removing it from the dictionary in the connectioninfo-class.

PasswordConnectionInfo connectionInfo = new PasswordConnectionInfo("server", 2227, "user", "password");
connectionInfo.Timeout = TimeSpan.FromMilliseconds(5000);
connectionInfo.Encryptions.Remove("3des-cbc");
SshClient sshClient = new SshClient(connectionInfo);
sshClient.Connect();

 The encryption appeard to be changed (to Renci.SshNet.Security.Cryptography.Ciphers.AesCipher) properly once the connection was established but the performance was the same.

// Magnus

 

Nov 7, 2011 at 4:17 PM

Hi Oleg,

I started to profile where the time was lost and found out that opening, closing, and disposing the channel is done for each command which seems to be quite expensive. I tried to use the Shell-class instead but I can't get it to run as stable as I want. Sometimes characters are lost and I have to play with the stream-positions in order to get it to work at all. However, when it works I get significantly better performance out of it.

Here's my testcode:

static void Main(string[] args)
{
    PasswordConnectionInfo connectionInfo = new PasswordConnectionInfo("server", 2247, "user", "pass");
    connectionInfo.Timeout = TimeSpan.FromMilliseconds(5000);
    SshClient sshClient = new SshClient(connectionInfo);
    sshClient.Connect();
    DateTime start = DateTime.Now;
    MemoryStream input = new MemoryStream();
    MemoryStream output = new MemoryStream();
            
    Shell shell = sshClient.CreateShell(input, output, output);
    shell.Start();
    DateTime start = DateTime.Now;

    long outputPosition = 0;
    Console.WriteLine(ReadUntil(output, ref outputPosition, ">"));
    foreach (string command in File.ReadAllLines(@"c:\temp\commands.txt"))
    {
        var pos = input.Position;
        byte[] bytes = Encoding.ASCII.GetBytes(command + "\r\n");
        input.Write(bytes, 0, bytes.Length);
        input.Position = pos;
        Console.WriteLine(ReadUntil(output, ref outputPosition, "sid@sis1> \r\nsid@sis1> "));
    }
    Console.WriteLine((DateTime.Now - start).TotalMilliseconds);
}
static string ReadUntil(Stream stream, ref long pos, string prompt)
{
    Console.WriteLine("ReadUntil pos {0}", pos);
    StringBuilder result = new StringBuilder();
    do
    {
        stream.Position = pos;
        StreamReader sr = new StreamReader(stream);
        string temp = sr.ReadToEnd();
        pos += temp.Length;
        result.Append(temp);
    }
    while (!result.ToString().Contains(prompt));
    return result.ToString();
}

 

Nov 7, 2011 at 4:36 PM

Hi,

Thanks for a reasearch,

I will take a a look at it and some other issues hopefully next week, and if not then the week after next, when I am back from conference.

As far as closing and opening, I will see if I can avoid that, but if I remeber correctly, SSH will not allow me to execute another command on the same channel, but I am not sure about that so will have to double check on that later.

 

Thanks,

Oleg

Nov 23, 2011 at 3:10 PM

Magnus,

 

Can you tell me what commercial library you tested where command execution was much faster?

I tried to execute command on the same channel without closing it but with no luck, so I just wonder how they do it, as far as what packets do they send.

 

Thanks,

Oleg

Nov 24, 2011 at 9:29 AM

Hi Oleg,

I use WeOnlyDo SSH-client. I have dumped the network-traffic with WireShark if you'd like to dig in more deeply what packet they send.

Best regards // Magnus

Nov 25, 2011 at 4:30 PM

ok, thanks,

 

I'll try to investigate it further.

 

Thanks,

Oleg

Apr 15, 2015 at 8:17 AM
Edited Apr 15, 2015 at 8:18 AM
Hi, wonder if you managed to find this issue.

I'm using sshnet to provide port forwarding for mysql backend of client application, and that does work great.

Recently, we decided to do some more processing on server side, and as mysql is not capable of dealing with more complicated stored procedures I have decided to try scripts.

Unfortunately on existing mysql connection I can process nearly 300 queries per second, while same calculation using .RunCommand() or async .BeginExecute() does avg 20 calls per sec. it is also very unstable, in a way that it does not keep one rate, rather sinusoid between 10-200.

For test I used command:
mysql: SELECT {0} * 2
script: "echo -n $(({0} * 2))"

Is there any way make sshnet process script calls faster?

Thanks
J