|
1 | 1 | import io |
| 2 | +import logging |
2 | 3 | import pathlib |
3 | | -from typing import Callable, List |
| 4 | +import time |
| 5 | +from typing import Callable, List, Tuple, Union |
4 | 6 |
|
5 | 7 | import pytest |
6 | 8 |
|
@@ -227,3 +229,63 @@ def test_files_api_upload_download(ucws, random): |
227 | 229 | assert f.read() == b"some text data" |
228 | 230 |
|
229 | 231 | w.files.delete(target_file) |
| 232 | + |
| 233 | + |
| 234 | +def test_files_api_read_twice_from_one_download(ucws, random): |
| 235 | + w = ucws |
| 236 | + schema = 'filesit-' + random() |
| 237 | + volume = 'filesit-' + random() |
| 238 | + with ResourceWithCleanup.create_schema(w, 'main', schema): |
| 239 | + with ResourceWithCleanup.create_volume(w, 'main', schema, volume): |
| 240 | + f = io.BytesIO(b"some text data") |
| 241 | + target_file = f'/Volumes/main/{schema}/{volume}/filesit-{random()}.txt' |
| 242 | + w.files.upload(target_file, f) |
| 243 | + |
| 244 | + res = w.files.download(target_file).contents |
| 245 | + |
| 246 | + with res: |
| 247 | + assert res.read() == b"some text data" |
| 248 | + |
| 249 | + with pytest.raises(ValueError): |
| 250 | + with res: |
| 251 | + res.read() |
| 252 | + |
| 253 | + |
| 254 | +@pytest.mark.benchmark |
| 255 | +def test_files_api_download_benchmark(ucws, random): |
| 256 | + w = ucws |
| 257 | + schema = 'filesit-' + random() |
| 258 | + volume = 'filesit-' + random() |
| 259 | + with ResourceWithCleanup.create_schema(w, 'main', schema): |
| 260 | + with ResourceWithCleanup.create_volume(w, 'main', schema, volume): |
| 261 | + # Create a 50 MB file |
| 262 | + f = io.BytesIO(bytes(range(256)) * 200000) |
| 263 | + target_file = f'/Volumes/main/{schema}/{volume}/filesit-benchmark-{random()}.txt' |
| 264 | + w.files.upload(target_file, f) |
| 265 | + |
| 266 | + totals = {} |
| 267 | + for chunk_size_kb in [20, 50, 100, 200, 500, 1000, 2000, 5000, 10000, 20000, 50000, None]: |
| 268 | + chunk_size = chunk_size_kb * 1024 if chunk_size_kb else None |
| 269 | + total = 0 |
| 270 | + count = 10 |
| 271 | + for i in range(count): |
| 272 | + start = time.time() |
| 273 | + f = w.files.download(target_file).contents |
| 274 | + f.set_chunk_size(chunk_size) |
| 275 | + with f as vf: |
| 276 | + vf.read() |
| 277 | + end = time.time() |
| 278 | + total += end - start |
| 279 | + avg_time = total / count |
| 280 | + logging.info(f"[chunk_size=%s] Average time to download: %f seconds", |
| 281 | + str(chunk_size_kb) + 'kb' if chunk_size_kb else 'None', avg_time) |
| 282 | + totals[chunk_size_kb] = avg_time |
| 283 | + logging.info("Benchmark results:") |
| 284 | + best: Tuple[Union[int, None], Union[float, None]] = (None, None) |
| 285 | + for k, v in totals.items(): |
| 286 | + if best[1] is None or v < best[1]: |
| 287 | + best = (k, v) |
| 288 | + logging.info(f"[chunk_size=%s] Average time to download: %f seconds", |
| 289 | + str(k) + 'kb' if k else 'None', v) |
| 290 | + min_str = str(best[0]) + "kb" if best[0] else "None" |
| 291 | + logging.info("Fastest chunk size: %s in %f seconds", min_str, best[1]) |
0 commit comments