Skip to content

Commit c8373c9

Browse files
committed
Eliminate intermediate copy to read buffer.
1 parent 4e2bd63 commit c8373c9

File tree

1 file changed

+41
-22
lines changed

1 file changed

+41
-22
lines changed

src/Renci.SshNet/Sftp/SftpFileStream.cs

Lines changed: 41 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -329,40 +329,59 @@ public override int Read(byte[] buffer, int offset, int count)
329329
while (count > 0)
330330
{
331331
// How much data do we have available in the buffer?
332-
var tempLen = _bufferLen - _bufferPosition;
333-
if (tempLen <= 0)
332+
var bytesAvailableInBuffer = _bufferLen - _bufferPosition;
333+
if (bytesAvailableInBuffer <= 0)
334334
{
335335
_bufferPosition = 0;
336+
_bufferLen = 0;
336337

337-
var data = _session.RequestRead(_handle, (ulong)_position, (uint)_readBufferSize);
338+
var data = _session.RequestRead(_handle, (ulong) _position, (uint) _readBufferSize);
338339

339-
_bufferLen = data.Length;
340-
_serverFilePosition = (ulong)_position;
340+
// TODO: don't we need to take into account the number of bytes read (data.Length) ?
341+
_serverFilePosition = (ulong) _position;
341342

342-
if (_bufferLen == 0)
343+
if (data.Length == 0)
343344
{
344345
break;
345346
}
346347

347-
Buffer.BlockCopy(data, 0, _readBuffer, 0, _bufferLen);
348-
tempLen = _bufferLen;
348+
// determine number of bytes that we can read into caller-provided buffer
349+
var bytesToWriteToCallerBuffer = Math.Min(data.Length, count);
350+
// write bytes to caller-provided buffer
351+
Buffer.BlockCopy(data, 0, buffer, offset, bytesToWriteToCallerBuffer);
352+
// advance offset to start writing bytes into caller-provided buffer
353+
offset += bytesToWriteToCallerBuffer;
354+
// update number of bytes left to read
355+
count -= bytesToWriteToCallerBuffer;
356+
// record total number of bytes read into caller-provided buffer
357+
readLen += bytesToWriteToCallerBuffer;
358+
// update stream position
359+
_position += bytesToWriteToCallerBuffer;
360+
361+
if (data.Length > bytesToWriteToCallerBuffer)
362+
{
363+
// copy remaining bytes to read buffer
364+
_bufferLen = data.Length - bytesToWriteToCallerBuffer;
365+
Buffer.BlockCopy(data, count, _readBuffer, 0, _bufferLen);
366+
}
349367
}
350-
351-
// Don't read more than the caller wants.
352-
if (tempLen > count)
368+
else
353369
{
354-
tempLen = count;
370+
// determine number of bytes that we can write from read buffer to caller-provided buffer
371+
var bytesToWriteToCallerBuffer = Math.Min(bytesAvailableInBuffer, count);
372+
// copy data from read buffer to the caller-provided buffer
373+
Buffer.BlockCopy(_readBuffer, _bufferPosition, buffer, offset, bytesToWriteToCallerBuffer);
374+
// update position in read buffer
375+
_bufferPosition += bytesToWriteToCallerBuffer;
376+
// advance offset to start writing bytes into caller-provided buffer
377+
offset += bytesAvailableInBuffer;
378+
// update number of bytes left to read
379+
count -= bytesToWriteToCallerBuffer;
380+
// record total number of bytes read into caller-provided buffer
381+
readLen += bytesToWriteToCallerBuffer;
382+
// update stream position
383+
_position += bytesToWriteToCallerBuffer;
355384
}
356-
357-
// Copy stream data to the caller's buffer.
358-
Buffer.BlockCopy(_readBuffer, _bufferPosition, buffer, offset, tempLen);
359-
360-
// Advance to the next buffer positions.
361-
readLen += tempLen;
362-
offset += tempLen;
363-
count -= tempLen;
364-
_bufferPosition += tempLen;
365-
_position += tempLen;
366385
}
367386
}
368387

0 commit comments

Comments
 (0)