Skip to content

Commit 5e4e347

Browse files
committed
Rework Vector_softRemove() and compact() operations
Remove the 'dirty_index' and 'dirty_count' members of Vector object. Instead, let the callers of the Vector_softRemove() operation track the 'dirtyIndex' and pass it to Vector_compact() when needed. (The new 'dirtyIndex' local variables are safe to migrate from 'int' to 'size_t' because no negative value is used.) 'dirty_index' is supposed to have shorter lifespan than a Vector instance, and by removing the member we can reduce object size. 'dirty_count' is redundant and thus removed as well. A boolean 'isDirty' member is added to a Vector object for ease of debugging. Signed-off-by: Kang-Che Sung <explorer09@gmail.com>
1 parent aa9fa65 commit 5e4e347

5 files changed

Lines changed: 46 additions & 56 deletions

File tree

ProcessTable.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@ static void ProcessTable_cleanupEntries(Table* super) {
6363
Machine* host = super->host;
6464
const Settings* settings = host->settings;
6565

66+
// Lowest index of the row that is soft-removed. Used to speed up
67+
// compaction.
68+
int dirtyIndex = Vector_size(super->rows);
69+
6670
// Finish process table update, culling any exit'd processes
6771
for (int i = Vector_size(super->rows) - 1; i >= 0; i--) {
6872
Process* p = (Process*) Vector_get(super->rows, i);
@@ -78,11 +82,13 @@ static void ProcessTable_cleanupEntries(Table* super) {
7882
if (pid > host->maxProcessId)
7983
host->maxProcessId = pid;
8084

81-
Table_cleanupRow(super, (Row*) p, i);
85+
if (!Table_cleanupRow(super, &p->super, i)) {
86+
dirtyIndex = i;
87+
}
8288
}
8389

8490
// compact the table in case of deletions
85-
Table_compact(super);
91+
Table_compact(super, dirtyIndex);
8692
}
8793

8894
const TableClass ProcessTable_class = {

Table.c

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,7 @@ void Table_prepareEntries(Table* this) {
329329
}
330330

331331
// tidy up Row state after refreshing the table
332-
void Table_cleanupRow(Table* table, Row* row, int idx) {
332+
Row* Table_cleanupRow(Table* table, Row* row, int idx) {
333333
Machine* host = table->host;
334334
const Settings* settings = host->settings;
335335

@@ -348,21 +348,28 @@ void Table_cleanupRow(Table* table, Row* row, int idx) {
348348
goto remove;
349349
}
350350
}
351-
return;
351+
return row;
352352

353353
remove:
354354
Table_removeIndex(table, row, idx);
355+
return NULL;
355356
}
356357

357358
void Table_cleanupEntries(Table* this) {
359+
// Lowest index of the row that is soft-removed. Used to speed up
360+
// compaction.
361+
int dirtyIndex = Vector_size(this->rows);
362+
358363
// Finish process table update, culling any removed rows
359364
for (int i = Vector_size(this->rows) - 1; i >= 0; i--) {
360365
Row* row = (Row*) Vector_get(this->rows, i);
361-
Table_cleanupRow(this, row, i);
366+
if (!Table_cleanupRow(this, row, i)) {
367+
dirtyIndex = i;
368+
}
362369
}
363370

364371
// compact the table in case of any earlier row removals
365-
Table_compact(this);
372+
Table_compact(this, dirtyIndex);
366373
}
367374

368375
const TableClass Table_class = {

Table.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -84,10 +84,10 @@ void Table_prepareEntries(Table* this);
8484

8585
void Table_cleanupEntries(Table* this);
8686

87-
void Table_cleanupRow(Table* this, Row* row, int idx);
87+
Row* Table_cleanupRow(Table* this, Row* row, int idx);
8888

89-
static inline void Table_compact(Table* this) {
90-
Vector_compact(this->rows);
89+
static inline void Table_compact(Table* this, int dirtyIndex) {
90+
Vector_compact(this->rows, dirtyIndex);
9191
this->needsSort = true;
9292
}
9393

Vector.c

Lines changed: 17 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,7 @@ Vector* Vector_new(const ObjectClass* type, bool owner, int size) {
2828
.items = 0,
2929
.type = type,
3030
.owner = owner,
31-
.dirty_index = -1,
32-
.dirty_count = 0,
31+
.isDirty = false,
3332
};
3433
return this;
3534
}
@@ -46,21 +45,11 @@ void Vector_delete(Vector* this) {
4645
free(this);
4746
}
4847

49-
static inline bool Vector_isDirty(const Vector* this) {
50-
if (this->dirty_count > 0) {
51-
assert(0 <= this->dirty_index && this->dirty_index < this->items);
52-
assert(this->dirty_count <= this->items);
53-
return true;
54-
}
55-
assert(this->dirty_index == -1);
56-
return false;
57-
}
58-
5948
#ifndef NDEBUG
6049

6150
static bool Vector_isConsistent(const Vector* this) {
6251
assert(this->items <= this->arraySize);
63-
assert(!Vector_isDirty(this));
52+
assert(!this->isDirty);
6453

6554
return true;
6655
}
@@ -100,8 +89,7 @@ void Vector_prune(Vector* this) {
10089
}
10190
}
10291
this->items = 0;
103-
this->dirty_index = -1;
104-
this->dirty_count = 0;
92+
this->isDirty = false;
10593
memset(this->array, '\0', this->arraySize * sizeof(Object*));
10694
}
10795

@@ -256,10 +244,7 @@ Object* Vector_softRemove(Vector* this, int idx) {
256244
if (removed) {
257245
this->array[idx] = NULL;
258246

259-
this->dirty_count++;
260-
if (this->dirty_index < 0 || idx < this->dirty_index) {
261-
this->dirty_index = idx;
262-
}
247+
this->isDirty = true;
263248

264249
if (this->owner) {
265250
Object_delete(removed);
@@ -270,35 +255,26 @@ Object* Vector_softRemove(Vector* this, int idx) {
270255
return removed;
271256
}
272257

273-
void Vector_compact(Vector* this) {
274-
if (!Vector_isDirty(this)) {
258+
void Vector_compact(Vector* this, int dirtyIndex) {
259+
if (!this->isDirty)
275260
return;
276-
}
277261

278-
const int size = this->items;
279-
assert(0 <= this->dirty_index && this->dirty_index < size);
280-
assert(this->array[this->dirty_index] == NULL);
262+
assert(0 <= dirtyIndex);
263+
if (dirtyIndex >= this->items)
264+
return;
281265

282-
int idx = this->dirty_index;
266+
assert(!this->array[dirtyIndex]);
283267

284-
// one deletion: use memmove, which should be faster
285-
if (this->dirty_count == 1) {
286-
memmove(&this->array[idx], &this->array[idx + 1], (this->items - idx - 1) * sizeof(this->array[0]));
287-
this->array[this->items - 1] = NULL;
288-
} else {
289-
// multiple deletions
290-
for (int i = idx + 1; i < size; i++) {
291-
if (this->array[i]) {
292-
this->array[idx++] = this->array[i];
293-
}
268+
for (int i = dirtyIndex + 1; i < this->items; i++) {
269+
if (this->array[i]) {
270+
this->array[dirtyIndex++] = this->array[i];
294271
}
295-
// idx is now at the end of the vector and on the first index which should be set to NULL
296-
memset(&this->array[idx], '\0', (size - idx) * sizeof(this->array[0]));
297272
}
273+
int dirtyCount = this->items - dirtyIndex;
274+
memset(&this->array[dirtyIndex], 0, dirtyCount * sizeof(this->array[0]));
298275

299-
this->items -= this->dirty_count;
300-
this->dirty_index = -1;
301-
this->dirty_count = 0;
276+
this->items = dirtyIndex;
277+
this->isDirty = false;
302278

303279
assert(Vector_isConsistent(this));
304280
}

Vector.h

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,13 @@ typedef struct Vector_ {
2020
int arraySize;
2121
int growthRate;
2222
int items;
23-
/* lowest index of a pending soft remove/delete operation,
24-
used to speed up compaction */
25-
int dirty_index;
26-
/* count of soft deletes, required for Vector_count to work in debug mode */
27-
int dirty_count;
23+
24+
/* If true, the items would be freed when they are removed from the
25+
vector. */
2826
bool owner;
27+
/* Whether the Vector is pending a "compact" operation. This field
28+
is currently only used for debugging. */
29+
bool isDirty;
2930
} Vector;
3031

3132
Vector* Vector_new(const ObjectClass* type, bool owner, int size);
@@ -54,7 +55,7 @@ Object* Vector_remove(Vector* this, int idx);
5455
Object* Vector_softRemove(Vector* this, int idx);
5556

5657
/* Vector_compact reclaims space free'd up by Vector_softRemove, if any. */
57-
void Vector_compact(Vector* this);
58+
void Vector_compact(Vector* this, int dirtyIndex);
5859

5960
void Vector_moveUp(Vector* this, int idx);
6061

0 commit comments

Comments
 (0)