Skip to content

Performance Tracking

The ProxyStore Store interface provides low-level performance tracking on store operations (e.g., get and set). Performance tracking is disable by default and can be enabled by passing stats=True to a Store constructor.

from proxystore.store.file import FileStore

store = FileStore(
   name="default",
   store_dir="/tmp/proxystore-dump",
   stats=True,
)

Performance statistics are aggregated on a per-key level and can be accessed via the Store.stats() method. Store.stats() takes a key (string) or Proxy and returns a dictionary mapping Store operations to TimeStats objects containing the aggregated statistics for the operation.

Warning

Performance statistics are local to each Store instance. In multi-process applications or applications that instantiate multiple Store instances, the statistics returned by Store.stats() will only represent a partial view of the overall performance.

Warning

Attempting to query Store.stats() without initializing the store to track stats will raise a ValueError.

Continuing with the above store object, an instance of FileStore configured to track performance statistics, we can perform operations on store and inspect the statistics. In the following block, we add an object to the store and see that there are now performance statistics on the FileStore.set() and FileStore.set_bytes() operations.

target = list(range(0, 100))
key = store.set(target)

stats = store.stats(key)
stats.keys()
# >>> dict_keys(['set_bytes', 'set'])
stats['set']
# >>> TimeStats(
# >>>     calls=1,
# >>>     avg_time_ms=0.0686,
# >>>     min_time_ms=0.0686,
# >>>     max_time_ms=0.0686,
# >>>     size_bytes=None,
# >>> )
stats['set_bytes']
# >>> TimeStats(
# >>>     calls=1,
# >>>     avg_time_ms=0.0339,
# >>>     min_time_ms=0.0339,
# >>>     max_time_ms=0.0339,
# >>>     size_bytes=219,
# >>> )

Operations that work directly on bytes (i.e., get_bytes() and set_bytes()) will also note the size of the byte array used in the operation in the TimeStats.size_bytes attribute. As more operations are performed on the store, more statistics will be accumulated.

target = store.get(key)
stats = store.stats(key)

stats.keys()
# >>> dict_keys(
# >>>     ['set_bytes', 'set', 'is_cached', 'get_bytes', 'exists', 'get']
# >>> )

# Attributes of `TimeStats` can be accessed directly
stats['get'].calls
# >>> 1
stats['get'].avg_time_ms
# >>> 0.0625

# Check that the avg time of `get` decreases due to caching
# when called twice in a row.
target = store.get(key)
stats = store.stats(key)
stats['get'].calls
# >>> 2
stats['get'].avg_time_ms
# >>> 0.0376

Performance statistics can also be accessed with a proxy.

target_proxy = store.proxy(target)
stats = store.stats(target_proxy)
stats.keys()
# >>> dict_keys(['set_bytes', 'set', 'proxy'])
stats['proxy'].avg_time_ms
# >>> 0.0691

Proxies produced by a store with performance tracking enabled will also track statistics on time taken to resolve itself. When Store.stats() is passed a proxy, the method will inspect the proxy for any performance statistics and include any statistics in the result.

# Access the proxy to force it to resolve.
target_proxy[0:5]
# >>> [0, 1, 2, 3, 4]

stats = store.stats(target_proxy)
stats.keys()
# >>> dict_keys(
# >>>     ['resolve', 'set_bytes', 'set', 'proxy',
# >>>      'is_cached', 'get_bytes', 'exists', 'get']
# >>> )
stats['resolve'].avg_time_ms
# >>> 0.0587

Python code used to generate the above examples can be found at https://github.com/proxystore/proxystore/blob/main/examples/store_stats.py.