Skip to content

Commit

Permalink
Fix compaction
Browse files Browse the repository at this point in the history
  • Loading branch information
conradz committed Jul 15, 2024
1 parent 6ae53f0 commit 0a8eadc
Show file tree
Hide file tree
Showing 3 changed files with 60 additions and 41 deletions.
54 changes: 26 additions & 28 deletions src/main/resources/runtime.c0
Original file line number Diff line number Diff line change
Expand Up @@ -25,53 +25,50 @@ int runtime_compact(FieldArray*[] contents, int capacity, int newId) {
start++;

int removed = 0;
int insert = -1;
int insert = start;
int i = start + 1;
while (i != start) {
FieldArray* entry = contents[i];
if (entry == NULL) {
// skip
} else if (entry->accessible == 0 && entry->id != newId) {
removed++;
if (insert == -1)
insert = i;
} else if (insert != -1) {
int psl = entry->psl;
if (psl == 0) {
// NULL all locations from `insert` up to `i`
while (insert != i) {
contents[insert] = NULL;
insert = (insert + 1) % capacity;
}

insert = -1;
} else {
} else {
if (insert != i) {
int psl = entry->psl;
// Calculate the distance between `insert` and `i`
// Allow `i` to wrap around before `insert` does
int distance = insert < i ? insert - i : capacity + i - insert;
int distance = insert <= i ? i - insert : capacity + i - insert;
if (psl < distance) {
// Only move up to `psl` spots backwards, otherwise it would be prior
// to the hash location
insert = (insert + distance - psl) % capacity;
int newInsert = (insert + distance - psl) % capacity;
while (insert != newInsert) {
contents[insert] = NULL;
insert = (insert + 1) % capacity;
}

distance = psl;
}

contents[insert] = entry;
insert = (insert + 1) % capacity;
entry->psl -= distance;
if (distance != 0) {
contents[insert] = entry;
entry->psl -= distance;
}

}

insert = (insert + 1) % capacity;
}

i = (i + 1) % capacity;
}

// `i == start`
if (insert != -1) {
// NULL all locations from `insert` up to `start` (which is already NULL)
while (insert != i) {
contents[insert] = NULL;
insert = (insert + 1) % capacity;
}
// NULL all locations from `insert` up to `start` (which is already NULL)
while (insert != i) {
contents[insert] = NULL;
insert = (insert + 1) % capacity;
}

return removed;
Expand All @@ -95,10 +92,11 @@ void runtime_grow(OwnedFields* fields, int newId)

// Check if we can gain enough space just by dropping unused entries
int unused = runtime_compact(contents, capacity, newId);
if (unused != 0)
if (unused != 0) {
fields->length -= unused;
if (unused >= GROW_CONST)
return;
if (unused >= GROW_CONST)
return;
}

// Otherwise, use a larger array and rehash
int newCapacity = capacity + GROW_CONST;
Expand Down
42 changes: 33 additions & 9 deletions src/test/resources/c0/quickcheck.c0
Original file line number Diff line number Diff line change
Expand Up @@ -155,13 +155,27 @@ void check_fields(OwnedFields* fields) {
assert(count == fields->length); // (2)
}

bool removeNext(int id, List* tags, OwnedFields* fields) {
int length = tags->length;
int[] values = tags->values;
for (int j = 0; j < length; j++) {
int t = values[j];
if (tag_id(t) == id) {
assert(runtime_tryRemove(fields, id, tag_field(t)));
list_remove(tags, t);
return true;
}
}
return false;
}

int main() {
int INITIAL_SIZE = 2048;
int MAX_ID = 1024;
int REPS = 2500;
int REPS = 5000;
bool PRINT = false;

rand_t r = init_rand(2);
rand_t r = init_rand(1);

List* tags = list_new();
int length = 0;
Expand Down Expand Up @@ -189,11 +203,11 @@ int main() {

// Check that tags coincides with the entries
// This takes a bit of time
for (int j = 0; j < tags->length; j++) {
/*for (int j = 0; j < tags->length; j++) {
int tag = tags->values[j];
runtime_assert(fields, tag_id(tag), tag_field(tag), "Missing field");
}
/*

for (int j = 0; j < fields->length; j++) {
FieldArray* entry = fields->contents[j];
if (entry != NULL) {
Expand All @@ -211,8 +225,8 @@ int main() {
int type = abs(rand(r)) % 100;
int id = abs(rand(r)) % MAX_ID;
int numFields = field_count(id);
if (type < 10) {
// 10% of the time: Add a struct
if (type < 15) {
// 15% of the time: Add a struct
if (!contains_id(tags, id)) {
if (PRINT) printf("addAll(%d, %d)\n", id, numFields);
runtime_addAll(fields, id, numFields);
Expand All @@ -232,8 +246,18 @@ int main() {
// if (PRINT) printf("Skipped: addAll(%d, %d)\n", id, numFields);
i--; // Don't count this iteration
}
} else if (type < 40) {
// 30% of the time: Add a single field
} else if (type < 30) {
// 15% of the time: Remove all fields for a single ID
if (contains_id(tags, id)) {
if (PRINT) printf("removeAll(%d, %d)\n", id, numFields);
while (removeNext(id, tags, fields))
true;
} else {
// if (PRINT) printf("Skipped: removeAll(%d)\n", id);
i--;
}
} else if (type < 70) {
// 40% of the time: Add a single field
int field = abs(rand(r)) % numFields;
int t = tag(id, field);
bool contained = list_contains(tags, t);
Expand All @@ -258,7 +282,7 @@ int main() {
assert(false);
}
} else {
// 60% of the time: Remove a single field
// 30% of the time: Remove a single field
int field = abs(rand(r)) % numFields;
int t = tag(id, field);
bool contained = list_contains(tags, t);
Expand Down
5 changes: 1 addition & 4 deletions src/test/resources/c0/test.c0
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ void test_remove() {
}

void test_resizing() {
println("test_resizing: ");
print("test_resizing: ");

OwnedFields* fields = runtime_init();

Expand Down Expand Up @@ -152,9 +152,7 @@ void test_resizingRemove() {
assert(fields->capacity == 1280);

// Verify that we still have access to IDs 1000-1022 and 2000-2999
runtime_print(fields);
for (int i = 1000; i < 1023; i++) {
printf("i: %d\n", i);
assert(checkAcc(fields, i, 0));
assert(checkAcc(fields, i, 1));
}
Expand Down Expand Up @@ -301,6 +299,5 @@ int main() {
test_ensureSeparate();

println("All runtime tests passed");
printint(-5 % 10);
return 0;
}

0 comments on commit 0a8eadc

Please sign in to comment.