Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
automatic1111
GitHub Repository: automatic1111/stable-diffusion-webui
Path: blob/master/modules/cache.py
3055 views
1
import json
2
import os
3
import os.path
4
import threading
5
6
import diskcache
7
import tqdm
8
9
from modules.paths import data_path, script_path
10
11
cache_filename = os.environ.get('SD_WEBUI_CACHE_FILE', os.path.join(data_path, "cache.json"))
12
cache_dir = os.environ.get('SD_WEBUI_CACHE_DIR', os.path.join(data_path, "cache"))
13
caches = {}
14
cache_lock = threading.Lock()
15
16
17
def dump_cache():
18
"""old function for dumping cache to disk; does nothing since diskcache."""
19
20
pass
21
22
23
def make_cache(subsection: str) -> diskcache.Cache:
24
return diskcache.Cache(
25
os.path.join(cache_dir, subsection),
26
size_limit=2**32, # 4 GB, culling oldest first
27
disk_min_file_size=2**18, # keep up to 256KB in Sqlite
28
)
29
30
31
def convert_old_cached_data():
32
try:
33
with open(cache_filename, "r", encoding="utf8") as file:
34
data = json.load(file)
35
except FileNotFoundError:
36
return
37
except Exception:
38
os.replace(cache_filename, os.path.join(script_path, "tmp", "cache.json"))
39
print('[ERROR] issue occurred while trying to read cache.json; old cache has been moved to tmp/cache.json')
40
return
41
42
total_count = sum(len(keyvalues) for keyvalues in data.values())
43
44
with tqdm.tqdm(total=total_count, desc="converting cache") as progress:
45
for subsection, keyvalues in data.items():
46
cache_obj = caches.get(subsection)
47
if cache_obj is None:
48
cache_obj = make_cache(subsection)
49
caches[subsection] = cache_obj
50
51
for key, value in keyvalues.items():
52
cache_obj[key] = value
53
progress.update(1)
54
55
56
def cache(subsection):
57
"""
58
Retrieves or initializes a cache for a specific subsection.
59
60
Parameters:
61
subsection (str): The subsection identifier for the cache.
62
63
Returns:
64
diskcache.Cache: The cache data for the specified subsection.
65
"""
66
67
cache_obj = caches.get(subsection)
68
if not cache_obj:
69
with cache_lock:
70
if not os.path.exists(cache_dir) and os.path.isfile(cache_filename):
71
convert_old_cached_data()
72
73
cache_obj = caches.get(subsection)
74
if not cache_obj:
75
cache_obj = make_cache(subsection)
76
caches[subsection] = cache_obj
77
78
return cache_obj
79
80
81
def cached_data_for_file(subsection, title, filename, func):
82
"""
83
Retrieves or generates data for a specific file, using a caching mechanism.
84
85
Parameters:
86
subsection (str): The subsection of the cache to use.
87
title (str): The title of the data entry in the subsection of the cache.
88
filename (str): The path to the file to be checked for modifications.
89
func (callable): A function that generates the data if it is not available in the cache.
90
91
Returns:
92
dict or None: The cached or generated data, or None if data generation fails.
93
94
The `cached_data_for_file` function implements a caching mechanism for data stored in files.
95
It checks if the data associated with the given `title` is present in the cache and compares the
96
modification time of the file with the cached modification time. If the file has been modified,
97
the cache is considered invalid and the data is regenerated using the provided `func`.
98
Otherwise, the cached data is returned.
99
100
If the data generation fails, None is returned to indicate the failure. Otherwise, the generated
101
or cached data is returned as a dictionary.
102
"""
103
104
existing_cache = cache(subsection)
105
ondisk_mtime = os.path.getmtime(filename)
106
107
entry = existing_cache.get(title)
108
if entry:
109
cached_mtime = entry.get("mtime", 0)
110
if ondisk_mtime > cached_mtime:
111
entry = None
112
113
if not entry or 'value' not in entry:
114
value = func()
115
if value is None:
116
return None
117
118
entry = {'mtime': ondisk_mtime, 'value': value}
119
existing_cache[title] = entry
120
121
dump_cache()
122
123
return entry['value']
124
125