Ben Cornelis
10/24/2025, 7:40 PM(raylet) node_manager.cc:3193: 1 Workers (tasks / actors) killed due to memory pressure (OOM) I've tried various k8s pod sizing - currently I have 80 worker pods with 8cpu / 32gb. Does anyone know why so much memory would be used, or how to tune / think about queries like this?Ben Cornelis
10/24/2025, 7:41 PMdf = daft.read_parquet(
"<abfs://my_container@my_service_account.dfs.core.windows.net/in_table_path/>"
)
df = df.select(col("group_col"), col("other_col"))
.groupby("group_col")
.agg_list(col("other_col"))
df.write_parquet("<abfs://my_container@my_service_account.dfs.core.windows.net/out_table_path/>")Desmond Cheong
10/24/2025, 7:49 PMimport daft
from daft import col
df = daft.read_parquet(
"<abfs://my_container@my_service_account.dfs.core.windows.net/in_table_path/>"
)
df = df.select(col("group_col"), col("other_col"))
df.write_parquet(
"<abfs://my_container@my_service_account.dfs.core.windows.net/tmp_grouped/>",
partition_cols=["group_col"],
)
# Stage 2
df = daft.read_parquet(
"<abfs://my_container@my_service_account.dfs.core.windows.net/tmp_grouped/>",
hive_partitioning=True,
)
df = df.groupby("group_col").agg_list(col("other_col"))
df.write_parquet(
"<abfs://my_container@my_service_account.dfs.core.windows.net/out_table_path/>"
)Ben Cornelis
10/24/2025, 8:41 PMDesmond Cheong
10/24/2025, 8:51 PMBen Cornelis
10/24/2025, 9:02 PM(raylet, ip=10.224.20.85) Spilled 8674 MiB, 866 objects, write throughput 1621 MiB/s, but not enough to keep the actor from getting killedBen Cornelis
10/24/2025, 10:14 PMPhysicalScan->PhysicalWrite 0: 0%| | 0.00/49.5k
Any ideas what could be happening there, or suggestions on how to debug? The tasks all eventually get queued up but none completeBen Cornelis
10/24/2025, 10:27 PMpartition_cols since when I remove that it writes fineDesmond Cheong
10/24/2025, 10:31 PMBen Cornelis
10/24/2025, 10:33 PMpartition_colsBen Cornelis
10/27/2025, 3:15 PMwrite_parquet was writing out a partition dir for each unique group_col value. In my case the set of group values has very high cardinality, so this would lead to a very large number of output files.Ben Cornelis
10/27/2025, 3:19 PMBen Cornelis
10/27/2025, 5:17 PMwrite_parquet. However, increasing the number of partitions to 2000 via df = df.repartition(2000, col("group_col")) worked! I guess that makes sense - if this group by operation can't be spilled to disk, then a ray worker node needs to have the entire partition in memory, and so increasing the number of partitions will decrease peak memory usage. Am I understanding that correctly?Desmond Cheong
10/27/2025, 5:40 PMagg_list a specific group_col needs to be fully aggregated before it can be flushed from memory. With the initial dataset, we don't know when we've seen all values belonging to a specific group_col until we've shuffled all the data
⢠By adding a partitioning step, all values belonging to a specific group_col now belong on the same worker on the same partition. So when we finally do the agg_list, on each worker, at most one partition needs to be materialized in-memory before we know that the `agg_list`s for belonging to that partition are completed. And whenever a batch of `agg_list`s is completed, it goes on to the next operator which is a write so it's removed from memory
⢠Also, your idea to do an in-memory repartitioning was a great choice! I should've led with that instead of suggesting to write out the data š
Ben Cornelis
10/27/2025, 6:59 PM