Three command-line clients, the same four servers, the same files, the same link, back to back. Every download was checked against its source before its time was counted. The method is described in Comparative benchmarks.
mod_dav behind nginx (WebDAV), OpenSSH (SFTP) and vsftpd with explicit TLS (FTP).aeroftp-cli export rclone and aeroftp-cli export cyberduck, so the three tools reached the same endpoints with the same credentials and TLS mode.| Operation | AeroFTP | rclone | Cyberduck CLI |
|---|---|---|---|
| 300 MiB upload | put | copyto | --upload |
| 300 MiB download | get | copyto | --download |
| Tree upload | --parallel 4 put -r | --transfers 4 copy | --parallel 4 --upload |
| Tree download | --parallel 4 get -r | --transfers 4 copy | --parallel 4 --download |
With their default settings, AeroFTP and rclone both ask for 4 ranges on a single download larger than about 250 MiB, so the 300 MiB download is meant to be multi-stream for both. For S3 the section below checks it with a connection count.
Seconds, lower is better. Each cell lists the counted runs of both passes. Every run in these tables passed its integrity check; the load average at the start of each run stayed between 0.57 and 4.62 on 12 cores, and each pass started only once the CPU had been under 35 percent for 45 seconds.
| Cell | AeroFTP | rclone | Cyberduck CLI | rclone / AeroFTP | duck / AeroFTP |
|---|---|---|---|---|---|
| 300 MiB file, upload | 10.64, 11.57 | 11.43, 11.15 | 14.39, 13.96 | 1.02 | 1.28 |
| 300 MiB file, download | 22.85, 18.67 | 14.53, 15.54 | 53.85, 48.60 | 0.72 | 2.47 |
| 200 files, upload | 3.81, 3.34 | 8.10, 7.50 | 8.35, 7.89 | 2.18 | 2.27 |
| 200 files, download | 3.60, 3.71 | 2.62, 2.77 | 6.08, 6.29 | 0.74 | 1.69 |
| Cell | AeroFTP | rclone | Cyberduck CLI | rclone / AeroFTP | duck / AeroFTP |
|---|---|---|---|---|---|
| 300 MiB file, upload | 12.02, 8.91 | 10.46, 9.43 | 12.33, 12.67 | 0.95 | 1.19 |
| 300 MiB file, download | 14.50, 17.87 | 20.31, 14.26 | 47.37, 43.08 | 1.07 | 2.79 |
| 200 files, upload | 3.59, 3.76 | 9.00, 9.18 | 9.11, 8.25 | 2.47 | 2.36 |
| 200 files, download | 3.86, 3.66 | 3.51, 3.37 | 6.58, 6.29 | 0.91 | 1.71 |
| Cell | AeroFTP | rclone | Cyberduck CLI | rclone / AeroFTP | duck / AeroFTP |
|---|---|---|---|---|---|
| 300 MiB file, upload | 23.30, 21.21 | 10.43, 11.84 | 19.11, 19.81 | 0.50 | 0.87 |
| 300 MiB file, download | 26.83, 23.01 | 19.44, 20.10 | 41.00, 40.48 | 0.79 | 1.63 |
| 200 files, upload | 13.05, 14.04 | 31.60, 30.59 | 18.66, 16.78 | 2.30 | 1.31 |
| 200 files, download | 9.24, 9.90 | 18.19, 16.81 | 15.55, 14.81 | 1.83 | 1.59 |
| Cell | AeroFTP | rclone | Cyberduck CLI | rclone / AeroFTP | duck / AeroFTP |
|---|---|---|---|---|---|
| 300 MiB file, upload | 10.91, 10.06 | 13.26, 11.95 | failed, exit 1 | 1.20 | n/a |
| 300 MiB file, download | 21.07, 21.46 | 21.22, 18.31 | failed, exit 1 | 0.93 | n/a |
| 200 files, upload | 17.90, 17.76 | 88.26, 91.49 | failed, exit 1 | 5.04 | n/a |
| 200 files, download | 22.73, 22.72 | 23.74, 24.98 | failed, exit 1 | 1.07 | n/a |
What these tables show on this link:
Resident memory at its peak, in MB, the highest of the counted runs.
| Cell | AeroFTP | rclone | Cyberduck CLI |
|---|---|---|---|
| S3 (MinIO), 300 MiB file, upload | 211 | 70 | 294 |
| S3 (MinIO), 300 MiB file, download | 81 | 68 | 292 |
| S3 (MinIO), 200 files, upload | 82 | 74 | 277 |
| S3 (MinIO), 200 files, download | 82 | 74 | 273 |
| WebDAV, 300 MiB file, upload | 82 | 69 | 557 |
| WebDAV, 300 MiB file, download | 81 | 55 | 282 |
| WebDAV, 200 files, upload | 83 | 59 | 328 |
| WebDAV, 200 files, download | 84 | 59 | 292 |
| SFTP, 300 MiB file, upload | 79 | 79 | 572 |
| SFTP, 300 MiB file, download | 162 | 74 | 257 |
| SFTP, 200 files, upload | 81 | 68 | 224 |
| SFTP, 200 files, download | 82 | 71 | 228 |
| FTP, explicit TLS, 300 MiB file, upload | 79 | 79 | n/a |
| FTP, explicit TLS, 300 MiB file, download | 81 | 65 | n/a |
| FTP, explicit TLS, 200 files, upload | 82 | 70 | n/a |
| FTP, explicit TLS, 200 files, download | 83 | 69 | n/a |
AeroFTP stayed between 79 and 84 MB on every cell but two: the S3 upload of the large file, which is a multipart upload (211 MB here; 262 MB in September, before aeroftp#882), and the SFTP download of the large file (162 MB). rclone stayed between 55 and 79 MB. Cyberduck CLI runs on a Java runtime and peaked between 224 and 572 MB.
One 300 MiB object on MinIO, downloaded by AeroFTP with --multi-thread-streams 1 and with 4 (its default), two runs each in alternating order, with rclone and its defaults as the control in the same window. During every AeroFTP run a sampler counted the TCP connections the process held to the S3 endpoint, so an arm labelled four streams is shown to open four.
| Arm | Runs, seconds | Connections seen |
|---|---|---|
| AeroFTP, 1 stream | 30.05, 31.70 | 1 |
| AeroFTP, 4 streams (default) | 23.56, 15.39 | 4 |
| rclone, defaults | 13.60, 14.82 | not sampled |
Four streams were faster than one by about 37 percent on the medians (30.88 s to 19.48 s). Four connections were open during each four-stream run and one during each single-stream run, which is consistent with the four range requests the code plans for this size; the requests themselves were not logged. The two four-stream runs differ by half, so the size of the gain is uncertain; its direction is not. With four streams AeroFTP stayed behind rclone on this object (ratio 0.73 on the medians), consistent with the S3 download row above.
duck 9.5.4 connects, authenticates and lists over explicit TLS, then fails every transfer, in both passes. On download the server answers 522 SSL connection failed: session reuse required: vsftpd requires each data connection to resume the TLS session of the control connection, and duck's data connections do not. On upload the server closes the connection without a message, which is consistent with the same requirement. duck exits 1 on every FTP cell, so no duck time is reported for FTP. In September a failed duck upload left a zero-byte file on the server, which another client then reads as a real file.
AeroFTP and rclone both complete over explicit TLS against the same server, the lab's vsftpd 3.0.5, which requires every data connection to reuse the control connection's TLS session (require_ssl_reuse, on by default). rclone completes only with TLS 1.3 disabled (disable_tls13): in September, rclone v1.74.0 with TLS 1.3 enabled failed with 426 Failure reading network stream, and on one tree download it exited 0 after delivering 16 of 200 files. That is what this server and these versions did, not a property of TLS 1.3 in general. AeroFTP caps FTP over TLS at TLS 1.2 because, with its TLS library, a TLS 1.3 session ticket is consumed when used and a second data connection would resume a different session than the control connection; aeroftp-cli export rclone writes disable_tls13 for every FTP remote with TLS since 4.2.0.
The lab's WebDAV server sits behind a TLS-terminating proxy, and it answered a folder path without a trailing slash with a redirect to the same path over plain http://. rclone 1.75.1 refuses to follow it, because it would send the credentials in cleartext; rclone 1.74.0, used in September, completed the same cells against this server. AeroFTP 4.2.1 did not hit the redirect in these operations. Since aeroftp#1011, merged after 4.2.1, AeroFTP also refuses to follow a redirect from HTTPS to HTTP and names the server misconfiguration in the error. The proxy was corrected before the WebDAV cells were measured (one proxy_redirect line), so every tool ran against the same, correct server.
The same harness ran on 19 September on a build between 4.1.9 and 4.2.0 (the head of aeroftp#880 at f9eaa87b), with rclone v1.74.0 and duck 9.5.4, one run per cell. Three of its findings changed the code before 4.2.0 shipped, which is why it is kept here rather than as its own page:
HEAD response through a call that always returns 0 for HEAD, so every S3 download ran on one stream while the client announced four. aeroftp#881 fixed it, and also pins every range request to the object's ETag so a file replaced during the download cannot be assembled from two versions. That 31.51 s describes the broken path and is not a before for the table above.mmap: on a 1 GiB upload with 16 MiB parts, three runs went from 295 to 312 MB down to 139 to 141 MB, with the same wall time.disable_tls13, and rclone failed against vsftpd, which requires the data connection to resume the control connection's TLS session. It exited 0 on a tree download that delivered 16 of 200 files. aeroftp#880 makes the exporter write disable_tls13 for every FTP remote with TLS. That session is not counted anywhere.