Merge pull request #123 from microsoft/low-memory-fix

Issue with low-memory notification
This commit is contained in:
Matthew Parkinson
2020-02-04 15:09:32 +00:00
committed by GitHub
5 changed files with 130 additions and 10 deletions

View File

@@ -1070,8 +1070,7 @@ namespace snmalloc
bool was_full = super->is_full();
SlabList* sl = &small_classes[sizeclass];
Slab* slab = Metaslab::get_slab(p);
Superslab::Action a =
slab->dealloc_slow(sl, super, p);
Superslab::Action a = slab->dealloc_slow(sl, super, p);
if (likely(a == Superslab::NoSlabReturn))
return;
stats().sizeclass_dealloc_slab(sizeclass);

View File

@@ -263,7 +263,7 @@ namespace snmalloc
{
lazy_decommit();
}
} while (old_epoch <= new_epoch);
} while (old_epoch < new_epoch);
}
}
#endif
@@ -403,13 +403,14 @@ namespace snmalloc
}
// Cross-reference largealloc's alloc() decommitted condition.
if ((decommit_strategy != DecommitNone)
&& (large_class != 0 || decommit_strategy == DecommitSuper))
if (
(decommit_strategy != DecommitNone) &&
(large_class != 0 || decommit_strategy == DecommitSuper))
{
size_t rsize = bits::one_at_bit(SUPERSLAB_BITS) << large_class;
memory_provider.notify_not_using(
pointer_offset(p, OS_PAGE_SIZE), rsize - OS_PAGE_SIZE);
pointer_offset(p, OS_PAGE_SIZE), rsize - OS_PAGE_SIZE);
}
stats.superslab_push();

View File

@@ -178,8 +178,8 @@ namespace snmalloc
// This does not need to remove the "use" as done by the fast path.
// Returns a complex return code for managing the superslab meta data.
// i.e. This deallocation could make an entire superslab free.
SNMALLOC_SLOW_PATH typename Superslab::Action dealloc_slow(
SlabList* sl, Superslab* super, void* p)
SNMALLOC_SLOW_PATH typename Superslab::Action
dealloc_slow(SlabList* sl, Superslab* super, void* p)
{
Metaslab& meta = super->get_meta(this);

View File

@@ -84,7 +84,7 @@ namespace snmalloc
{
if (kind != Fresh)
{
// If this wasn't previously Fresh, we need to zero some things.
// If this wasn't previously Fresh, we need to zero some things.
used = 0;
for (size_t i = 0; i < SLAB_COUNT; i++)
{
@@ -105,7 +105,8 @@ namespace snmalloc
{
curr = (curr + meta[curr].next + 1) & (SLAB_COUNT - 1);
}
if (curr != 0) abort();
if (curr != 0)
abort();
for (size_t i = 0; i < SLAB_COUNT; i++)
{

View File

@@ -0,0 +1,119 @@
#include <iostream>
#include <snmalloc.h>
#include <test/measuretime.h>
#include <test/setup.h>
#include <unordered_set>
#include <vector>
using namespace snmalloc;
struct Node
{
Node* next;
};
class Queue
{
Node* head;
Node* tail;
Node* new_node(size_t size)
{
auto result = (Node*)ThreadAlloc::get()->alloc(size);
result->next = nullptr;
return result;
}
public:
Queue()
{
head = new_node(1);
tail = head;
}
void add(size_t size)
{
tail->next = new_node(size);
tail = tail->next;
}
void try_remove()
{
if (head->next == nullptr)
return;
Node* next = head->next;
ThreadAlloc::get()->dealloc(head);
head = next;
}
};
bool has_pressure()
{
static thread_local uint64_t epoch;
if constexpr (!pal_supports<LowMemoryNotification, GlobalVirtual>)
{
return false;
}
uint64_t current_epoch = default_memory_provider.low_memory_epoch();
bool result = epoch != current_epoch;
epoch = current_epoch;
return result;
}
void reach_pressure(Queue& allocations)
{
size_t size = 4096;
while (!has_pressure())
{
allocations.add(size);
allocations.try_remove();
allocations.add(size);
allocations.add(size);
}
}
void reduce_pressure(Queue& allocations)
{
size_t size = 4096;
for (size_t n = 0; n < 1000; n++)
{
allocations.try_remove();
allocations.try_remove();
allocations.add(size);
}
}
int main(int, char**)
{
#ifndef NDEBUG
Queue allocations;
if constexpr (!pal_supports<LowMemoryNotification, GlobalVirtual>)
{
std::cout << "Pal does not support low-memory notification! Test not run"
<< std::endl;
return 0;
}
# if defined(WIN32) && !defined(SNMALLOC_VA_BITS_64)
std::cout << "32-bit windows not supported for this test." << std::endl;
# else
setup();
for (size_t i = 0; i < 10; i++)
{
reach_pressure(allocations);
std::cout << "Pressure " << i << std::endl;
reduce_pressure(allocations);
}
# endif
#else
std::cout << "Release test only." << std::endl;
#endif
return 0;
}