phpseclib/phpseclib — pull request #129 by johnsterling (2013-07-12 14:42:26+00:00)
Title: Optimization by replacing _string_shift()

I found that `Net_SFTP->put()` with in-memory data would take significantly longer than when using `NET_SFTP_LOCAL_FILE`. As a simple test, I was putting a 10MB file in about 1.5s, but it would take about 21.8s when reading the file into a string first. I also noticed the PHP process using 100% of a core when putting from a string.

I tracked the issue down to the use of `Net_SSH2->_string_shift()` to emulate advancing a pointer through the string containing the data. This function "shifts" data off the front of the string by making a new copy of the string containing only the remaining data. For large strings, this causes a lot of CPU load since it's in a tight loop writing the data.

I was able to bring the performance back in line with `NET_SFTP_LOCAL_FILE` by simply substituting `substr()`, which I believe doesn't copy the source string, and simply copies out the much shorter substring requested.

I notice that `_string_shift()` is used throughout the project, but most of the instances I have found are not in tight loops, and are mostly used in parsing server responses and such. So, it could probably be optimized out in those cases but likely isn't worth the effort of the slight refactor (i.e. updating a position index and ensuring the entire string isn't read afterward).

Anyway, this was a pretty trivial change but I thought it deserved some discussion so I made it a pull request. If there are other cases where a noticeable gain could be had, I would be glad to add some additional commits, as well.