Commit 0a9f647
perf: stream SFTP uploads/downloads instead of buffering whole file (#195)
* perf: stream SFTP uploads/downloads instead of buffering whole file
Upload (`upload_file`, `upload_dir_recursive`) used `tokio::fs::read` to
load the entire local file into a `Vec<u8>` before calling `write_all`,
and download (`download_file`, `download_dir_recursive`) used
`read_to_end` into a pooled buffer + `clone()` to a separate `Vec`
before writing locally. For multi-GB transfers this means peak RSS
scales with file size and large files OOM the client.
Replace each path with a small `stream_copy()` helper that loops on
256 KiB reads and writes through the existing `AsyncRead`/`AsyncWrite`
implementations on `tokio::fs::File` and `russh_sftp::client::fs::File`.
Buffer size matches the SFTP MAX_WRITE_LENGTH so each chunk maps to a
single SFTP packet without further fragmentation.
Verified locally on macOS arm64 against `bssh-server` v2.1.3 over
loopback with a 1 GiB file:
| Op | Build | real | RSS |
|----------|------------|---------|----------|
| upload | unpatched | 38.65s | 3.23 GB |
| upload | streaming | 3.47s | 20 MB |
| download | unpatched | 3.93s | 2.17 GB |
| download | streaming | 3.41s | 16 MB |
Peak RSS drops ~160x and uploads complete ~11x faster (a single
multi-MB `write_all` apparently serializes much worse through the SFTP
pipeline than 256 KiB chunked writes).
* fix: align SFTP streaming chunking
Match the streaming buffer to russh-sftp's 255 KiB packet limit so each chunk stays within one SFTP read/write request, explicitly close downloaded remote handles after successful copies, and cover the chunking behavior with a focused unit test.
---------
Co-authored-by: Jeongkyu Shin <inureyes@gmail.com>1 parent 27d20e4 commit 0a9f647
3 files changed
Lines changed: 103 additions & 25 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
12 | 12 | | |
13 | 13 | | |
14 | 14 | | |
15 | | - | |
| 15 | + | |
16 | 16 | | |
17 | 17 | | |
18 | 18 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
29 | 29 | | |
30 | 30 | | |
31 | 31 | | |
| 32 | + | |
| 33 | + | |
32 | 34 | | |
33 | 35 | | |
34 | 36 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
23 | 23 | | |
24 | 24 | | |
25 | 25 | | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
26 | 50 | | |
27 | | - | |
28 | 51 | | |
29 | 52 | | |
30 | 53 | | |
| |||
46 | 69 | | |
47 | 70 | | |
48 | 71 | | |
49 | | - | |
50 | | - | |
| 72 | + | |
| 73 | + | |
51 | 74 | | |
52 | 75 | | |
53 | 76 | | |
54 | | - | |
55 | 77 | | |
56 | 78 | | |
57 | 79 | | |
58 | 80 | | |
59 | 81 | | |
60 | 82 | | |
61 | | - | |
| 83 | + | |
62 | 84 | | |
63 | 85 | | |
64 | 86 | | |
| |||
89 | 111 | | |
90 | 112 | | |
91 | 113 | | |
92 | | - | |
93 | | - | |
94 | | - | |
95 | | - | |
96 | | - | |
97 | | - | |
| 114 | + | |
| 115 | + | |
98 | 116 | | |
99 | 117 | | |
100 | 118 | | |
101 | | - | |
102 | | - | |
103 | | - | |
| 119 | + | |
| 120 | + | |
| 121 | + | |
| 122 | + | |
| 123 | + | |
104 | 124 | | |
105 | 125 | | |
106 | 126 | | |
| |||
173 | 193 | | |
174 | 194 | | |
175 | 195 | | |
176 | | - | |
177 | | - | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
178 | 199 | | |
179 | 200 | | |
180 | 201 | | |
| |||
185 | 206 | | |
186 | 207 | | |
187 | 208 | | |
188 | | - | |
189 | | - | |
| 209 | + | |
190 | 210 | | |
191 | 211 | | |
192 | 212 | | |
| |||
265 | 285 | | |
266 | 286 | | |
267 | 287 | | |
268 | | - | |
| 288 | + | |
269 | 289 | | |
270 | 290 | | |
271 | 291 | | |
272 | | - | |
273 | | - | |
274 | | - | |
275 | | - | |
276 | | - | |
| 292 | + | |
| 293 | + | |
| 294 | + | |
| 295 | + | |
| 296 | + | |
| 297 | + | |
| 298 | + | |
| 299 | + | |
277 | 300 | | |
278 | 301 | | |
| 302 | + | |
279 | 303 | | |
280 | 304 | | |
281 | 305 | | |
282 | 306 | | |
283 | 307 | | |
284 | 308 | | |
285 | 309 | | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
| 317 | + | |
| 318 | + | |
| 319 | + | |
| 320 | + | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
| 333 | + | |
| 334 | + | |
| 335 | + | |
| 336 | + | |
| 337 | + | |
| 338 | + | |
| 339 | + | |
| 340 | + | |
| 341 | + | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
| 346 | + | |
| 347 | + | |
| 348 | + | |
| 349 | + | |
| 350 | + | |
| 351 | + | |
| 352 | + | |
| 353 | + | |
| 354 | + | |
| 355 | + | |
| 356 | + | |
| 357 | + | |
| 358 | + | |
| 359 | + | |
| 360 | + | |
| 361 | + | |
0 commit comments