MCPcopy Create free account
hub / github.com/modelscope/modelscope / _get_file_hash_async

Function _get_file_hash_async

modelscope/utils/file_utils.py:302–378  ·  view source on GitHub ↗

Compute SHA256 with async I/O double-buffering for high-latency storage. Uses a producer-consumer pattern: a background thread reads file chunks into a bounded queue while the main thread computes the hash. This overlaps I/O latency with CPU computation.

(
    file_path: Union[str, Path],
    buffer_size_mb: int = 16,
    tqdm_desc: Optional[str] = '[Calculating]',
    disable_tqdm: Optional[bool] = True,
)

Source from the content-addressed store, hash-verified

300
301
302def _get_file_hash_async(
303 file_path: Union[str, Path],
304 buffer_size_mb: int = 16,
305 tqdm_desc: Optional[str] = '[Calculating]',
306 disable_tqdm: Optional[bool] = True,
307) -> dict:
308 """Compute SHA256 with async I/O double-buffering for high-latency storage.
309
310 Uses a producer-consumer pattern: a background thread reads file chunks
311 into a bounded queue while the main thread computes the hash. This
312 overlaps I/O latency with CPU computation.
313 """
314 import queue
315 import threading
316
317 from tqdm.auto import tqdm
318
319 file_path = str(file_path)
320 declared_size = os.path.getsize(file_path)
321 buffer_size = buffer_size_mb * 1024 * 1024
322
323 chunk_queue = queue.Queue(maxsize=2) # Bounded to limit memory usage
324 read_error = [None] # Mutable container for thread error propagation
325
326 def _producer():
327 try:
328 with open(file_path, 'rb') as f:
329 while True:
330 chunk = f.read(buffer_size)
331 if not chunk:
332 break
333 chunk_queue.put(chunk)
334 except Exception as e:
335 read_error[0] = e
336 finally:
337 chunk_queue.put(None) # Sentinel to signal EOF
338
339 reader_thread = threading.Thread(target=_producer, daemon=True)
340 reader_thread.start()
341
342 file_hash = hashlib.sha256()
343 bytes_hashed = 0
344 progress = tqdm(
345 total=declared_size,
346 desc=tqdm_desc,
347 disable=disable_tqdm,
348 dynamic_ncols=True,
349 unit='B',
350 unit_scale=True,
351 unit_divisor=1024,
352 )
353
354 while True:
355 chunk = chunk_queue.get()
356 if chunk is None:
357 break
358 file_hash.update(chunk)
359 bytes_hashed += len(chunk)

Callers 1

compute_file_hashFunction · 0.85

Calls 4

startMethod · 0.45
getMethod · 0.45
updateMethod · 0.45
closeMethod · 0.45

Tested by

no test coverage detected

Used in the wild real call sites across dependent graphs

searching dependent graphs…