1111from vllm .utils import cdiv , logger
1212from vllm .v1 .core .sched .output import NewRequestData
1313
14+ DEFAULT_GLOBAL_SEGMENT_SIZE = 3355443200 # 3.125 GiB
15+ DEFAULT_LOCAL_BUFFER_SIZE = 1073741824 # 1.0 GiB
1416
1517@dataclass
1618class MooncakeEngineMetadata :
@@ -419,7 +421,7 @@ class LasyerMultiBlockReqMeta:
419421class MooncakeStoreConfig :
420422 local_hostname : str
421423 metadata_server : str
422- global_segment_size : int
424+ global_segment_size : int | str
423425 local_buffer_size : int
424426 protocol : str
425427 device_name : str
@@ -433,8 +435,12 @@ def from_file(file_path: str) -> "MooncakeStoreConfig":
433435 return MooncakeStoreConfig (
434436 local_hostname = config .get ("local_hostname" ),
435437 metadata_server = config .get ("metadata_server" ),
436- global_segment_size = config .get ("global_segment_size" , 3355443200 ),
437- local_buffer_size = config .get ("local_buffer_size" , 1073741824 ),
438+ global_segment_size = _parse_global_segment_size (
439+ config .get ("global_segment_size" , DEFAULT_GLOBAL_SEGMENT_SIZE )
440+ ),
441+ local_buffer_size = _parse_global_segment_size (
442+ config .get ("local_buffer_size" , DEFAULT_LOCAL_BUFFER_SIZE )
443+ ),
438444 protocol = config .get ("protocol" , "tcp" ),
439445 device_name = config .get ("device_name" , "" ),
440446 master_server_address = config .get ("master_server_address" ),
@@ -446,4 +452,75 @@ def load_from_env() -> "MooncakeStoreConfig":
446452 if not config_path :
447453 raise ValueError (
448454 "The environment variable 'MOONCAKE_CONFIG_PATH' is not set." )
449- return MooncakeStoreConfig .from_file (config_path )
455+ return MooncakeStoreConfig .from_file (config_path )
456+
457+
458+ def _parse_global_segment_size (value ) -> int :
459+ """
460+ Parse storage size strings with support for units: GB, MB, KB, B
461+
462+ Args:
463+ value: Input value (int, str, or other convertible types)
464+
465+ Returns:
466+ int: Size in bytes
467+
468+ Raises:
469+ ValueError: For invalid format, missing number, or negative values
470+ TypeError: For unsupported input types
471+ """
472+
473+ if isinstance (value , int ):
474+ return value
475+ elif not isinstance (value , str ):
476+ try :
477+ return int (value )
478+ except (TypeError , ValueError ) as e :
479+ raise TypeError (f"Unsupported type for global_segment_size: { type (value )} " ) from e
480+ # Clean input string
481+ cleaned_input = value .strip ().lower ()
482+ if not cleaned_input :
483+ raise ValueError ("global segment size cannot be empty." )
484+
485+ UNIT_MULTIPLIERS = {
486+ 'gb' : 1024 ** 3 , # 1 GB = 1024^3 bytes
487+ 'mb' : 1024 ** 2 , # 1 MB = 1024^2 bytes
488+ 'kb' : 1024 , # 1 KB = 1024 bytes
489+ 'b' : 1 # 1 B = 1 byte
490+ }
491+ # Check for unit suffixes
492+ for unit , multiplier in UNIT_MULTIPLIERS .items ():
493+ if cleaned_input .endswith (unit ):
494+ number_part = cleaned_input [:- len (unit )].strip ()
495+ if not number_part :
496+ raise ValueError (f"Missing numeric value before unit '{ unit } ' in: '{ value } '" )
497+ return _convert_to_bytes (number_part , multiplier , value )
498+ # Handle unit-less input (bytes)
499+ return _convert_to_bytes (cleaned_input , 1 , value )
500+
501+
502+ def _convert_to_bytes (number_str : str , multiplier : int , original_input : str ) -> int :
503+ """
504+ Convert numeric string to byte count
505+
506+ Args:
507+ number_str: Numeric portion of input
508+ multiplier: Unit conversion factor
509+ original_input: Original input string (for error messages)
510+
511+ Returns:
512+ int: Byte count
513+
514+ Raises:
515+ ValueError: For invalid numbers or negative results
516+ """
517+ try :
518+ numeric_value = float (number_str )
519+ except ValueError :
520+ raise ValueError (f"Invalid numeric value '{ number_str } ' in: '{ original_input } '" )
521+ # Calculate byte count
522+ try :
523+ byte_count = int (numeric_value * multiplier )
524+ except OverflowError :
525+ raise ValueError (f"Storage size too large: '{ original_input } '" )
526+ return byte_count
0 commit comments