Skip to content

Accumulation of memory usage with large number of dense array queries #2194

@adamrboxall

Description

@adamrboxall

Hi, I'm hoping someone will be able to help us resolve a memory issue with TileDB-Py...

When running a large number of queries against a TileDB dense array, we are seeing an accumulation of memory usage. This can run into several GBs and eventually causes an out of memory error.

It seems periodically re-instantiating the TileDB context object leads to controlled memory usage - this suggests memory is held by the context object and correctly released when the context object is garbage collected. Unfortunately, adding this logic to periodically re-instantiate the TileDB context object isn't a practical solution for our more complex scripts (i.e. with multiple open arrays in PyTorch Datasets, requirement to track the number of queries when re-instantiating the context etc.), so we're hoping we can resolve this issue.

This occurs even when sm.tile_cache_size is set to 0.

This may be related to #150 or #440.

Please see a reproducible example below.

Thanks everyone for your help!


Python version:

Python 3.10.12

Python environment:

numpy==2.2.5
packaging==25.0
psutil==7.0.0
tiledb==0.34.0

Create a test array:

import numpy as np
import tiledb
import os
import psutil
import datetime

x = np.ones(10000000)
ctx = tiledb.default_ctx({"sm.tile_cache_size": 0, "sm.io_concurrency_level": 1, "sm.compute_concurrency_level": 1})
path = 'test_tile_db'
d1 = tiledb.Dim(
    'test_domain', domain=(0, x.shape[0] - 1), tile=10000, dtype="uint32"
)
domain = tiledb.Domain(d1)
v = tiledb.Attr(
    'test_value',
    dtype="float32",
)
schema = tiledb.ArraySchema(
    domain=domain, attrs=(v,), cell_order="row-major", tile_order="row-major"
)
A = tiledb.DenseArray.create(path, schema)
values = x.astype(np.float32)
with tiledb.DenseArray(path, mode="w", ctx=ctx) as A:
    A[:] = {'test_value': values}

Run a large number of queries and track memory usage:

ctx = tiledb.Ctx({"sm.tile_cache_size": 0, "sm.io_concurrency_level": 1, "sm.compute_concurrency_level": 1})
data = tiledb.open(path, mode='r', ctx=ctx)

for i in range(100000):
    array = data[0]
    if i % 10000 == 0:
        process = psutil.Process(os.getpid())
        ram_usage = process.memory_info().rss / 1e6
        print(datetime.datetime.now(), ram_usage, 'MB', 'after', i, 'queries')
2025-05-15 10:37:23.794463 157.769728 MB after 0 queries
2025-05-15 10:37:38.979566 283.578368 MB after 10000 queries
2025-05-15 10:37:52.696840 413.016064 MB after 20000 queries
2025-05-15 10:38:06.442493 542.4128 MB after 30000 queries
2025-05-15 10:38:19.806429 671.66208 MB after 40000 queries
2025-05-15 10:38:33.460704 801.017856 MB after 50000 queries
2025-05-15 10:38:47.761755 930.164736 MB after 60000 queries
2025-05-15 10:39:02.624914 1059.328 MB after 70000 queries
2025-05-15 10:39:17.331571 1189.036032 MB after 80000 queries
2025-05-15 10:39:33.014144 1318.25664 MB after 90000 queries

Controlled memory usage when periodically re-instantiating the context object:

ctx = tiledb.Ctx({"sm.tile_cache_size": 0, "sm.io_concurrency_level": 1, "sm.compute_concurrency_level": 1})
data = tiledb.open(path, mode='r', ctx=ctx)

for i in range(100000):
    
    array = data[0]

    if i % 10000 == 0:
        ctx = tiledb.Ctx({"sm.tile_cache_size": 0, "sm.io_concurrency_level": 1, "sm.compute_concurrency_level": 1})
        data = tiledb.open(path, mode='r', ctx=ctx)
        process = psutil.Process(os.getpid())  
        ram_usage = process.memory_info().rss / 1e6  
        print(datetime.datetime.now(), ram_usage, 'MB', 'after', i, 'queries') 
2025-05-15 10:41:44.234509 161.562624 MB after 0 queries
2025-05-15 10:41:57.731925 290.267136 MB after 10000 queries
2025-05-15 10:42:10.923391 290.267136 MB after 20000 queries
2025-05-15 10:42:24.230450 290.312192 MB after 30000 queries
2025-05-15 10:42:37.653962 290.033664 MB after 40000 queries
2025-05-15 10:42:51.223860 284.045312 MB after 50000 queries
2025-05-15 10:43:04.061728 285.372416 MB after 60000 queries
2025-05-15 10:43:17.623785 284.352512 MB after 70000 queries
2025-05-15 10:43:31.396821 283.860992 MB after 80000 queries
2025-05-15 10:43:45.231651 284.598272 MB after 90000 queries

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions