microsoft / microsoft/mimalloc
memory reclamation
Nobody has claimed this yet.
- Dominant language
- C
- Stars
- 13.4k
- Forks
- 1.2k
- Avg merge
- 4d 45m
- Merged PRs (30d)
- 13
Description
hi! doing some investigations on the mimalloc performance, i ran into some issues where mimalloc is rather aggressively retaining memory instead of releasing it back to the OS.
consider these two test cases of producer/consumer (1M of 1kb objects allocated, then deallocated) from (a) separate threads and (b) the same thread.
the performance characteristics are rather different from glibc's: the mimalloc retains a lot of memory, while glibc returns almost all memory to the OS.
in the multi-threaded test, i'm experiencing the following:
* glibc seems to have some thread-local pools, but when consumer is done (but not joined), about half the memory is returned to the OS. the other half is returned when the producer thread is joined
* with mimalloc no memory is returned to the OS when after `free` or joining the threads. about 50% is released when calling `mi_collect(true)`.
similar behaviour seems to happen in the single-threaded test, though in this case glibc releases all memory immediately.
i've seen this in a real-world program where memory tends to pile up. and while it can be reused in the process, it's not available for other processes. this makes me wonder if the heuristics for 'collection' passes could potentially be tweaked to reclaim memory more aggressively?
```
#include
#include
#include
int multi_threaded_test()
{
boost::concurrent::sync_queue sq;
boost::barrier producer_done(2), consumer_done(2), consumer_joined(2);
std::thread producer([&] {
for(int i = 0; i != 1'000'000; ++i) {
void *mem = malloc(1024);
sq.push(mem);
}
fprintf(stderr, "producer done\n");
producer_done.wait();
fprintf(stderr, "waiting for consumer\n");
consumer_done.wait();
std::this_thread::sleep_for(std::chrono::seconds(8));
fprintf(stderr, "producer destroyed\n");
});
producer_done.wait();
std::this_thread::sleep_for(std::chrono::seconds(5));
fprintf(stderr, "spawning consumer\n");
std::thread consumer([&] {
for(int i = 0; i != 1'000'000; ++i) {
void *mem = sq.pull();
free(mem);
}
fprintf(stderr, "consumer done\n");
consumer_done.wait();
std::this_thread::sleep_for(std::chrono::seconds(16));
fprintf(stderr, "consumer destroyed\n");
consumer_joined.wait();
});
consumer_joined.wait();
fprintf(stderr, "joining consumer\n");
consumer.join();
std::this_thread::sleep_for(std::chrono::seconds(5));
fprintf(stderr, "joining producer\n");
producer.join();
std::this_thread::sleep_for(std::chrono::seconds(5));
fprintf(stderr, "collecting\n");
mi_collect(true);
std::this_thread::sleep_for(std::chrono::seconds(5));
return 0;
}
int single_threaded_test()
{
boost::concurrent::sync_queue sq;
for(int i = 0; i != 1'000'000; ++i) {
void *mem = malloc(1024);
sq.push(mem);
}
fprintf(stderr, "freeing\n");
for(int i = 0; i != 1'000'000; ++i) {
void *mem = sq.pull();
free(mem);
}
fprintf(stderr, "done\n");
std::this_thread::sleep_for(std::chrono::seconds(5));
fprintf(stderr, "collecting\n");
mi_collect(true);
std::this_thread::sleep_for(std::chrono::seconds(5));
return 0;
}
int main()
{
return multi_threaded_test();
// return single_threaded_test();
}
```
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by running the supplied multi_threaded_test and single_threaded_test, comparing memory retention after free, thread joins, and mi_collect(true) with glibc. Trace the collection behavior responsible for the difference and determine whether more aggressive reclamation is appropriate; done means the behavior is explained and any change is validated against both test cases.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- cpp
- Domain
- operating-systems, performance
- Issue type
- Bug
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Stale
- Clarity
- Needs clarification
- Newbie friendliness
- 30/100