Skip to content

Memory manager triggers unnecessary spills #2829

@richox

Description

@richox

Describe the bug

currently, each requester can allocate at most (pool_size - tracker_total) / num_requesters memory. if an execution plan is skewed there will be a lot of memory wasted and unexpected spills.

for example, when we perform sort -> merge joining on two inputs, and one of them is very small:

SortMergeJoin {
    left: Sort { // bigger input
    },
    right: Sort { // smaller input
    },
    ...
}

the bigger sorter can use only half of the total memory, which will trigger more spills and slow down the performance.

To Reproduce

in the following case, we have 3 requesters requesting 90 of 100 memory. as the memory is not used up, there would be no spills during the execution. but the big requester actually spills every time.

    #[tokio::test]
    async fn multiple_skewed_requesters() {
        let config = RuntimeConfig::new()
            .with_memory_manager(MemoryManagerConfig::try_new_limit(100, 1.0).unwrap());
        let runtime = Arc::new(RuntimeEnv::new(config).unwrap());

        let big_requester1 = DummyRequester::new(0, runtime.clone());
        runtime.register_requester(&big_requester1.id);
        let small_requester2 = DummyRequester::new(0, runtime.clone());
        runtime.register_requester(&small_requester2.id);
        let small_requester3 = DummyRequester::new(0, runtime.clone());
        runtime.register_requester(&small_requester3.id);

        small_requester2.do_with_mem(5).await.unwrap();
        small_requester3.do_with_mem(5).await.unwrap();

        big_requester1.do_with_mem(40).await.unwrap();
        big_requester1.do_with_mem(40).await.unwrap();
        assert_eq!(big_requester1.get_spills(), 0); // assertion fails, actually = 2
    }

Expected behavior

spill only when all memory is used up. the spill strategy can be optimized, for example we can find out the maximum requester and let it spill.

Additional context
Add any other context about the problem here.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions