Skip to content

Commit

Permalink
[mycpp/runtime refactor] Make Dict Slab policy more like the List one
Browse files Browse the repository at this point in the history
It's simplified, because all the key, value, and index Slabs should all
be the same size.
  • Loading branch information
Andy C committed Feb 12, 2023
1 parent 1555c28 commit 6b7ce77
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 17 deletions.
15 changes: 14 additions & 1 deletion mycpp/gc_dict.h
Expand Up @@ -37,6 +37,11 @@ List<T>* ListFromDictSlab(Slab<int>* index, Slab<T>* slab, int n) {

template <class K, class V>
class Dict {
// Relates to minimum slab size. This is good for Dict<K*, V*>, Dict<K*,
// int>, Dict<int, V*>, but possibly suboptimal for Dict<int, int>. But that
// case is rare.
static const int kMinItems = 4;

public:
Dict()
: GC_CLASS_FIXED(header_, field_mask(), sizeof(Dict)),
Expand Down Expand Up @@ -121,6 +126,14 @@ class Dict {
}

DISALLOW_COPY_AND_ASSIGN(Dict)

private:
int RoundCapacity(int n) {
if (n < kMinItems) {
return kMinItems;
}
return RoundUp(n);
}
};

template <typename K, typename V>
Expand Down Expand Up @@ -157,7 +170,7 @@ void Dict<K, V>::reserve(int n) {
//
if (capacity_ < n) { // TODO: use load factor, not exact fit
// calculate the number of keys and values we should have
capacity_ = RoundUp(n + kCapacityAdjust) - kCapacityAdjust;
capacity_ = RoundCapacity(n + kCapacityAdjust) - kCapacityAdjust;

// TODO: This is SPARSE. How to compute a size that ensures a decent
// load factor?
Expand Down
9 changes: 2 additions & 7 deletions mycpp/gc_list.h
Expand Up @@ -25,18 +25,13 @@ class GlobalList {

template <typename T>
class List {
// TODO: Move methods that don't allocate or resize: out of gc_heap?
// - allocate: append(), extend()
// - resize: pop(), clear()
// - neither: reverse(), sort() -- these are more like functions. Except
// sort() is a templated method that depends on type param T.
// - neither: index(), slice()

// Relate slab size to number of items (capacity)
// 8 / 4 = 2 items, or 8 / 8 = 1 item
static const int kCapacityAdjust = kSlabHeaderSize / sizeof(T);
static_assert(kSlabHeaderSize % sizeof(T) == 0,
"Slab header size should be multiple of item size");

// Relates to minimum Slab size.
// Smallest non-empty List<T*> should have about 4 items, or 3 without header
// Smallest non-empty List<int> should have about 8 items, or 7 without header
static const int kMinItems = 32 / sizeof(T);
Expand Down
14 changes: 5 additions & 9 deletions mycpp/gc_slab.h
Expand Up @@ -6,18 +6,14 @@
#include "mycpp/common.h" // DISALLOW_COPY_AND_ASSIGN
#include "mycpp/gc_obj.h" // GC_OBJ

// Return the size of a resizeable allocation. For now we just round up by
// powers of 2. This could be optimized later. CPython has an interesting
// policy in listobject.c.
// Return the size of a resizeable allocation. Just round up to the nearest
// power of 2. (CPython has an interesting policy in listobject.c.)
//
// https://stackoverflow.com/questions/466204/rounding-up-to-next-power-of-2
inline int RoundUp(int n) {
// Note: List::RoundCapacity refines this. TODO: remove this check when we
// have Dict::RoundCapacity.
if (n < 4) {
return 4;
}
//
// Used by List<T> and Dict<K, V>.

inline int RoundUp(int n) {
// TODO: what if int isn't 32 bits?
n--;
n |= n >> 1;
Expand Down

0 comments on commit 6b7ce77

Please sign in to comment.