Send file contents in chunks
ClosedPublic

Authored by fvogt on Sep 12 2018, 9:43 AM.

Details

Summary

The KIO protocol can only send a maximum of 0xFFFFFF bytes of data.
TransferJob has an additional limit of 14 MiB.

BUG: 375765

Test Plan

Downloaded a 132MiB file, no more "slave died unexpectedly".
Size and md5sum match.

Diff Detail

Repository
R219 KIO GDrive
Lint
Automatic diff as part of commit; lint not applicable.
Unit
Automatic diff as part of commit; unit tests not applicable.
fvogt requested review of this revision.Sep 12 2018, 9:43 AM
fvogt created this revision.
fvogt updated this revision to Diff 41479.Sep 12 2018, 3:11 PM

Use same value as kio-sftp

fvogt edited the summary of this revision. (Show Details)Sep 12 2018, 3:11 PM

Thanks a lot for working on this.

What about a fixed chunk size? TransferJob seems to recommend 1MB at most:

/**
 * Request for data.
 * Please note, that you shouldn't put too large chunks
 * of data in it as this requires copies within the frame
 * work, so you should rather split the data you want
 * to pass here in reasonable chunks (about 1MB maximum)
 *
 * @param job the job that emitted this signal
 * @param data buffer to fill with data to send to the
 * slave. An empty buffer indicates end of data. (EOD)
 */
void dataReq(KIO::Job *job, QByteArray &data);

We definitely need to improve the documentation of this stuff. Adding @dfaure for more insights

fvogt added a comment.Sep 15 2018, 2:59 PM

The bigger, the better (=faster).
The 0xFFFFFF limit in KIO itself is due to the protocol only having 24 bits for size AFAIK - KLocalSocket can handle more than that at once without copying.
I'm not sure where TransferJob is used actually. It worked fine with more than 14MiB as well.

The only reason to use a smaller chunk size is to work better over TCP, but who uses KIO over TCP nowadays?

Yes to chunking.

Yes to changing the documentation, the 1MB must be very old in there, if 14MB works then let's say so.

As to the implementation, would it be possible to use QByteArray::fromRawData to avoid copying? After all it's all "synchronous" here, i.e. the lifetime of the chunk will always be less than the lifetime of the overall data.

fvogt updated this revision to Diff 41738.Sep 16 2018, 9:12 AM

Use QByteArray::fromRawData

src/kio_gdrive.cpp
639

Nitpick: data() instead of data (also in the comment below)

644

const?

645

Since QByteArray::fromRawData() takes an int, we could just make transferred and nextChunk also int. That would make the cast unnecessary.

fvogt updated this revision to Diff 41770.Sep 16 2018, 7:32 PM

Address comments.

fvogt marked 3 inline comments as done.Sep 16 2018, 7:32 PM
fvogt added inline comments.
src/kio_gdrive.cpp
645

Sure. I didn't believe the documentation as that means a QByteArray can never exceed 2GiB in size.

How is this looking now that D15426 has gone in?

elvisangelaccio accepted this revision.Sep 23 2018, 9:48 AM

Please push to the stable branch (1.2). Thanks!

src/kio_gdrive.cpp
642

data() also here

This revision is now accepted and ready to land.Sep 23 2018, 9:48 AM
This revision was automatically updated to reflect the committed changes.
fvogt marked an inline comment as done.

! In D15448#330352, @ngraham wrote:
How is this looking now that D15426 has gone in?

Those diffs are fully independant - this fixes the bug that larger file transfers (over 16MiB) simply failed at the end while D15426 improves performance of all transfers using the KIO AccessManager massively by removing the 100% CPU bottleneck.