Ren'Py Persistent Object Size Limit Configuration for Low-Traffic Workloads
0 reputation · 25 Jul 2024, 14:28 UTC
0 reputation · 25 Jul 2024, 14:28 UTC
Goal: Minimize the disk footprint of Ren'Py save games for a low‑traffic visual novel by controlling how much data is stored in the persistent object across playthroughs.
Constraint: The engine documentation does not expose a direct setting to cap the size of persistent data or to automatically prune old entries, yet the cautions note that uncontrolled growth can increase load times and bloat save files.
Uncertainty: It is unclear whether developers can enforce a maximum size, enable compression, or trigger selective cleanup of persistent variables without modifying the core engine.
Questions: Is there a configuration option or runtime call to limit the persistent object’s size? Can persistent data be segmented or expired based on playthrough count? Does Ren'Py provide a hook to compress or serialize persistent data more efficiently?
Ren'Py does not expose a configuration flag or built‑in API that caps the size of the persistent object, nor does it automatically prune old entries or compress the pickle file. The engine serializes persistent to persistent.py using Python’s pickle module, and that file is written uncompressed by default.
persistent.save() routine (or edit the block in persistent.py) to compress the pickle payload with zlib, gzip, or a similar library.init python:
if not persistent.playthrough_count:
persistent.playthrough_count = 0
label start:
$ persistent.playthrough_count += 1
# ... game logic ...
init python:
def prune_persistent(max_entries=100):
# Example: keep only the most recent 100 keys
keys = list(persistent.__dict__.keys())
if len(keys) > max_entries:
for k in keys[:-max_entries]:
del persistent[k]
$ prune_persistent()
init python:
import zlib, pickle
def persistent_save():
# Serialize normally
data = pickle.dumps(persistent.__dict__)
# Compress
compressed = zlib.compress(data)
# Write to file
with open(os.path.join(persistent_dir, "persistent.py"), "wb") as f:
f.write(compressed)
# Hook into Ren'Py’s save routine
init python:
persistent.save = persistent_save
persistent.py size before and after adding the compression hook.persistent.py.
persistent_save hook enabled and record the time taken to load a save.Which Ren'Py version are you using? Some newer releases expose persistent.save() as a public method, while older ones require editing persistent.py directly. Knowing the exact version will help tailor the override correctly.
Use comments to ask for clarification. Post a solution as an answer.
5,750 reputation · 26 Jul 2024, 02:08 UTC
Ren'Py 7.x–8.x does not expose a config.persistent_max_size or any automatic pruning hook. The persistent object is pickled wholesale to game/saves/persistent whenever renpy.save_persistent() runs (on quit, at checkpoints, or when you call it).
A maintainable mitigation is to wrap writes in a small helper that enforces a soft key-count or byte budget before pickling:
def save_persistent_budget(max_keys=200, max_bytes=64*1024):
# optional: archive stale keys to a side JSON first
if len(persistent.__dict__) > max_keys:
renpy.log.warn(f"Persistent keys ({len(persistent.__dict__)}) exceed budget")
renpy.save_persistent()
Call this instead of the raw function. Because pickle serializes nested structures verbosely, keeping values flat (bool, int, str) and moving playthrough-scoped data into regular save slots yields the biggest size reduction. Mobile/console sandbox quotas make this budget check especially valuable.