Compare commits
3 Commits
81ada88dc1
...
756e8168fb
| Author | SHA1 | Date | |
|---|---|---|---|
| 756e8168fb | |||
|
|
fbc0f833dc | ||
|
|
06e8177f0b |
File diff suppressed because it is too large
Load Diff
@@ -53,4 +53,5 @@
|
|||||||
*.gif filter=lfs diff=lfs merge=lfs -text
|
*.gif filter=lfs diff=lfs merge=lfs -text
|
||||||
*.sbs filter=lfs diff=lfs merge=lfs -text
|
*.sbs filter=lfs diff=lfs merge=lfs -text
|
||||||
*.sbsar filter=lfs diff=lfs merge=lfs -text
|
*.sbsar filter=lfs diff=lfs merge=lfs -text
|
||||||
*.spp filter=lfs diff=lfs merge=lfs -text
|
*.spp filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.usd filter=lfs diff=lfs merge=lfs -text
|
||||||
@@ -53,6 +53,7 @@ STATE_SUFFIX = ".meta.json"
|
|||||||
DEFAULT_CONFIG = {
|
DEFAULT_CONFIG = {
|
||||||
"zipper": "7z",
|
"zipper": "7z",
|
||||||
"compression": 9,
|
"compression": 9,
|
||||||
|
"compressionMethod": "LZMA2", # Compression method: LZMA2 (multi-threaded), PPMd (single-threaded), BZip2, Deflate
|
||||||
"dailyFormat": "daily_YYMMDD",
|
"dailyFormat": "daily_YYMMDD",
|
||||||
"Max7zInst": 0, # Maximum concurrent 7z instances (0 = auto-calculate)
|
"Max7zInst": 0, # Maximum concurrent 7z instances (0 = auto-calculate)
|
||||||
}
|
}
|
||||||
@@ -119,6 +120,12 @@ if not isinstance(COMPRESSION_LEVEL, int):
|
|||||||
COMPRESSION_LEVEL = 9
|
COMPRESSION_LEVEL = 9
|
||||||
COMPRESSION_LEVEL = max(0, min(9, COMPRESSION_LEVEL))
|
COMPRESSION_LEVEL = max(0, min(9, COMPRESSION_LEVEL))
|
||||||
|
|
||||||
|
COMPRESSION_METHOD = CONFIG.get("compressionMethod", "LZMA2")
|
||||||
|
# Validate compression method
|
||||||
|
valid_methods = {"LZMA2", "PPMd", "BZip2", "Deflate"}
|
||||||
|
if COMPRESSION_METHOD not in valid_methods:
|
||||||
|
COMPRESSION_METHOD = "LZMA2" # Default to LZMA2 for multi-threading support
|
||||||
|
|
||||||
MAX_7Z_INSTANCES = CONFIG.get("Max7zInst", 0)
|
MAX_7Z_INSTANCES = CONFIG.get("Max7zInst", 0)
|
||||||
if MAX_7Z_INSTANCES is not None:
|
if MAX_7Z_INSTANCES is not None:
|
||||||
if isinstance(MAX_7Z_INSTANCES, str):
|
if isinstance(MAX_7Z_INSTANCES, str):
|
||||||
@@ -543,7 +550,7 @@ def state_path_for(zip_path: Path) -> Path:
|
|||||||
return zip_path.with_suffix(zip_path.suffix + STATE_SUFFIX)
|
return zip_path.with_suffix(zip_path.suffix + STATE_SUFFIX)
|
||||||
|
|
||||||
|
|
||||||
def zip_sequence(seq_dir: Path, zip_path: Path, per_job_memory_limit: int | None = None) -> None:
|
def zip_sequence(seq_dir: Path, zip_path: Path, per_job_memory_limit: int | None = None, worker_count: int = 1, *, verbose: bool = False) -> None:
|
||||||
if ZIPPER_TYPE == "7z":
|
if ZIPPER_TYPE == "7z":
|
||||||
if SEVEN_Z_EXE is None:
|
if SEVEN_Z_EXE is None:
|
||||||
raise RuntimeError(
|
raise RuntimeError(
|
||||||
@@ -603,16 +610,54 @@ def zip_sequence(seq_dir: Path, zip_path: Path, per_job_memory_limit: int | None
|
|||||||
"-t7z", # Use 7z format, not zip
|
"-t7z", # Use 7z format, not zip
|
||||||
]
|
]
|
||||||
|
|
||||||
# Always use fixed dictionary size: 1GB (1024MB)
|
# Set compression method and memory/dictionary size based on method
|
||||||
# The per_job_memory_limit parameter is the estimated RAM usage (for logging/info only)
|
# PPMd uses memory parameter in method string, LZMA2 uses -md flag
|
||||||
# We keep dictionary at 1GB for best compression regardless of RAM estimate
|
|
||||||
FIXED_DICT_SIZE_MB = 1024
|
FIXED_DICT_SIZE_MB = 1024
|
||||||
cmd.append(f"-md={FIXED_DICT_SIZE_MB}m")
|
if COMPRESSION_METHOD == "PPMd":
|
||||||
|
# PPMd: specify memory as part of method string
|
||||||
|
cmd.append(f"-m0=PPMd:mem={FIXED_DICT_SIZE_MB}m")
|
||||||
|
elif COMPRESSION_METHOD == "LZMA2":
|
||||||
|
# LZMA2: use -md for dictionary size
|
||||||
|
cmd.append("-m0=LZMA2")
|
||||||
|
cmd.append(f"-md={FIXED_DICT_SIZE_MB}m")
|
||||||
|
elif COMPRESSION_METHOD == "BZip2":
|
||||||
|
# BZip2: use -md for dictionary size (smaller max: 900KB)
|
||||||
|
max_bzip2_dict = min(FIXED_DICT_SIZE_MB, 900) # BZip2 max is 900KB
|
||||||
|
cmd.append("-m0=BZip2")
|
||||||
|
cmd.append(f"-md={max_bzip2_dict}k")
|
||||||
|
elif COMPRESSION_METHOD == "Deflate":
|
||||||
|
# Deflate: doesn't use dictionary size parameter
|
||||||
|
cmd.append("-m0=Deflate")
|
||||||
|
else:
|
||||||
|
# Fallback: use LZMA2
|
||||||
|
cmd.append("-m0=LZMA2")
|
||||||
|
cmd.append(f"-md={FIXED_DICT_SIZE_MB}m")
|
||||||
|
|
||||||
|
# CPU thread allocation: when there's only 1 worker, use all CPU cores
|
||||||
|
# When there are multiple workers, use auto mode to let 7z decide
|
||||||
|
# Note: PPMd is single-threaded and won't benefit from -mmt
|
||||||
|
cpu_cores = os.cpu_count() or 1
|
||||||
|
if COMPRESSION_METHOD == "PPMd":
|
||||||
|
# PPMd is single-threaded, so -mmt won't help
|
||||||
|
# But we can still set it for consistency
|
||||||
|
cmd.append("-mmt=on")
|
||||||
|
elif worker_count == 1:
|
||||||
|
# Single worker: use all CPU cores for maximum speed (LZMA2, BZip2, Deflate support this)
|
||||||
|
cmd.append(f"-mmt={cpu_cores}")
|
||||||
|
else:
|
||||||
|
# Multiple workers: use auto mode (7z will manage threads)
|
||||||
|
cmd.append("-mmt=on")
|
||||||
|
|
||||||
cmd.extend([
|
cmd.extend([
|
||||||
str(temp_zip_abs),
|
str(temp_zip_abs),
|
||||||
f"@{list_file_abs}",
|
f"@{list_file_abs}",
|
||||||
])
|
])
|
||||||
|
|
||||||
|
# Log the command in verbose mode for debugging
|
||||||
|
if verbose:
|
||||||
|
cmd_str = " ".join(cmd)
|
||||||
|
log("zip", f"7z command: {cmd_str}", verbose_only=True, verbose=verbose)
|
||||||
|
|
||||||
result = subprocess.run(
|
result = subprocess.run(
|
||||||
cmd,
|
cmd,
|
||||||
cwd=seq_dir,
|
cwd=seq_dir,
|
||||||
@@ -728,9 +773,9 @@ def expand_sequence(zip_path: Path, seq_state: dict) -> None:
|
|||||||
os.utime(file_path, ns=(entry["mtime_ns"], entry["mtime_ns"]))
|
os.utime(file_path, ns=(entry["mtime_ns"], entry["mtime_ns"]))
|
||||||
|
|
||||||
|
|
||||||
def process_zip(seq_dir: Path, zip_path: Path, state_path: Path, seq_state: dict, per_job_memory_limit: int | None, *, verbose: bool) -> Sequence[Path]:
|
def process_zip(seq_dir: Path, zip_path: Path, state_path: Path, seq_state: dict, per_job_memory_limit: int | None, worker_count: int, *, verbose: bool) -> Sequence[Path]:
|
||||||
log("zip", f"{seq_dir} -> {zip_path}", verbose_only=True, verbose=verbose)
|
log("zip", f"{seq_dir} -> {zip_path}", verbose_only=True, verbose=verbose)
|
||||||
zip_sequence(seq_dir, zip_path, per_job_memory_limit)
|
zip_sequence(seq_dir, zip_path, per_job_memory_limit, worker_count, verbose=verbose)
|
||||||
state_path.write_text(json.dumps(seq_state, indent=2))
|
state_path.write_text(json.dumps(seq_state, indent=2))
|
||||||
return (zip_path, state_path)
|
return (zip_path, state_path)
|
||||||
|
|
||||||
@@ -859,7 +904,7 @@ def run_zip(requested_workers: int | None, *, verbose: bool) -> int:
|
|||||||
|
|
||||||
with ThreadPoolExecutor(max_workers=worker_count) as executor:
|
with ThreadPoolExecutor(max_workers=worker_count) as executor:
|
||||||
future_map = {
|
future_map = {
|
||||||
executor.submit(process_zip, seq_dir, zip_path, state_path, seq_state, ram_limits_dict.get(seq_dir), verbose=verbose): seq_dir
|
executor.submit(process_zip, seq_dir, zip_path, state_path, seq_state, ram_limits_dict.get(seq_dir), worker_count, verbose=verbose): seq_dir
|
||||||
for seq_dir, zip_path, state_path, seq_state in work_items
|
for seq_dir, zip_path, state_path, seq_state in work_items
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -983,7 +1028,7 @@ def main() -> int:
|
|||||||
if ZIPPER_TYPE == "7z":
|
if ZIPPER_TYPE == "7z":
|
||||||
exe = SEVEN_Z_EXE or "not found"
|
exe = SEVEN_Z_EXE or "not found"
|
||||||
max_inst = MAX_7Z_INSTANCES if MAX_7Z_INSTANCES is not None else "auto"
|
max_inst = MAX_7Z_INSTANCES if MAX_7Z_INSTANCES is not None else "auto"
|
||||||
log("init", f"7z executable: {exe}, Max7zInst: {max_inst}")
|
log("init", f"7z executable: {exe}, Max7zInst: {max_inst}, method: {COMPRESSION_METHOD}, level: {COMPRESSION_LEVEL}")
|
||||||
|
|
||||||
if args.mode == "expand":
|
if args.mode == "expand":
|
||||||
# For expand mode, use simple CPU-based worker calculation
|
# For expand mode, use simple CPU-based worker calculation
|
||||||
|
|||||||
Reference in New Issue
Block a user