Ver Fonte

Improve SFTP performance on medium/high latency connections (#866)

* Improve SFTP performance on medium-high latency connections
- Increases maxPendingReads from 10 to 100
- Increases socket send/receive buffer to 10 SSH packets (320K)

* Fix merge

* Adjust SFTP FileReader testcases to accept new MaxPendingReads values

* Fix CreateSftpFileReader testcase, make it dependant on MaxPendingReads constant

---------

Co-authored-by: Pedro Fonseca <pfonseca@qti.qualcomm.com>
Pedro Fonseca há 1 ano atrás
pai
commit
2eec748b18

+ 1 - 1
src/Renci.SshNet/Connection/ConnectorBase.cs

@@ -49,7 +49,7 @@ namespace Renci.SshNet.Connection
             {
                 SocketAbstraction.Connect(socket, ep, timeout);
 
-                const int socketBufferSize = 2 * Session.MaximumSshPacketSize;
+                const int socketBufferSize = 10 * Session.MaximumSshPacketSize;
                 socket.SendBufferSize = socketBufferSize;
                 socket.ReceiveBufferSize = socketBufferSize;
                 return socket;

+ 2 - 2
src/Renci.SshNet/ServiceFactory.cs

@@ -143,7 +143,7 @@ namespace Renci.SshNet
         /// </returns>
         public ISftpFileReader CreateSftpFileReader(string fileName, ISftpSession sftpSession, uint bufferSize)
         {
-            const int defaultMaxPendingReads = 3;
+            const int defaultMaxPendingReads = 10;
 
             // Issue #292: Avoid overlapping SSH_FXP_OPEN and SSH_FXP_LSTAT requests for the same file as this
             // causes a performance degradation on Sun SSH
@@ -163,7 +163,7 @@ namespace Renci.SshNet
             {
                 var fileAttributes = sftpSession.EndLStat(statAsyncResult);
                 fileSize = fileAttributes.Size;
-                maxPendingReads = Math.Min(10, (int) Math.Ceiling((double) fileAttributes.Size / chunkSize) + 1);
+                maxPendingReads = Math.Min(100, (int)Math.Ceiling((double)fileAttributes.Size / chunkSize) + 1);
             }
             catch (SshException ex)
             {

+ 1 - 1
test/Renci.SshNet.Tests/Classes/ServiceFactoryTest_CreateSftpFileReader_EndLStatThrowsSshException.cs

@@ -59,7 +59,7 @@ namespace Renci.SshNet.Tests.Classes
                             .Setup(p => p.EndLStat(_statAsyncResult))
                             .Throws(new SshException());
             _sftpSessionMock.InSequence(seq)
-                            .Setup(p => p.CreateFileReader(_handle, _sftpSessionMock.Object, _chunkSize, 3, null))
+                            .Setup(p => p.CreateFileReader(_handle, _sftpSessionMock.Object, _chunkSize, 10, null))
                             .Returns(_sftpFileReaderMock.Object);
         }
 

+ 5 - 3
test/Renci.SshNet.Tests/Classes/ServiceFactoryTest_CreateSftpFileReader_FileSizeIsMoreThanTenTimesGreaterThanChunkSize.cs → test/Renci.SshNet.Tests/Classes/ServiceFactoryTest_CreateSftpFileReader_FileSizeIsMoreThanMaxPendingReadsTimesChunkSize.cs

@@ -8,7 +8,7 @@ using Renci.SshNet.Tests.Common;
 namespace Renci.SshNet.Tests.Classes
 {
     [TestClass]
-    public class ServiceFactoryTest_CreateSftpFileReader_FileSizeIsMoreThanTenTimesGreaterThanChunkSize
+    public class ServiceFactoryTest_CreateSftpFileReader_FileSizeIsMoreThanMaxPendingReadsTimesChunkSize
     {
         private ServiceFactory _serviceFactory;
         private Mock<ISftpSession> _sftpSessionMock;
@@ -22,18 +22,20 @@ namespace Renci.SshNet.Tests.Classes
         private SftpFileAttributes _fileAttributes;
         private long _fileSize;
         private ISftpFileReader _actual;
+        private int _maxPendingReads;
 
         private void SetupData()
         {
             var random = new Random();
 
+            _maxPendingReads = 100;
             _bufferSize = (uint)random.Next(1, int.MaxValue);
             _openAsyncResult = new SftpOpenAsyncResult(null, null);
             _handle = CryptoAbstraction.GenerateRandom(random.Next(1, 10));
             _statAsyncResult = new SFtpStatAsyncResult(null, null);
             _fileName = random.Next().ToString();
             _chunkSize = (uint) random.Next(1000, 5000);
-            _fileSize = _chunkSize * random.Next(11, 50);
+            _fileSize = _chunkSize * random.Next(_maxPendingReads + 1, _maxPendingReads * 2);
             _fileAttributes = new SftpFileAttributesBuilder().WithSize(_fileSize).Build();
         }
 
@@ -63,7 +65,7 @@ namespace Renci.SshNet.Tests.Classes
                             .Setup(p => p.EndLStat(_statAsyncResult))
                             .Returns(_fileAttributes);
             _sftpSessionMock.InSequence(seq)
-                            .Setup(p => p.CreateFileReader(_handle, _sftpSessionMock.Object, _chunkSize, 10, _fileSize))
+                            .Setup(p => p.CreateFileReader(_handle, _sftpSessionMock.Object, _chunkSize, _maxPendingReads, _fileSize))
                             .Returns(_sftpFileReaderMock.Object);
         }