Changeset: de90ccd28a1c for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/de90ccd28a1c
Modified Files:
gdk/gdk_system.c
gdk/gdk_system.h
Branch: Jul2021
Log Message:
Make lock stats faster to use by using a doubly linked list.
Deleting random entries from a singly linked list is really expensive.
diffs (127 lines):
diff --git a/gdk/gdk_system.c b/gdk/gdk_system.c
--- a/gdk/gdk_system.c
+++ b/gdk/gdk_system.c
@@ -73,6 +73,7 @@ sortlocklist(MT_Lock *l)
r = r->next;
}
ll->next = NULL; /* break list into two */
+ r->prev = NULL;
/* recursively sort both sublists */
l = sortlocklist(l);
r = sortlocklist(r);
@@ -92,6 +93,7 @@ sortlocklist(MT_Lock *l)
t = ll = l;
} else {
ll->next = l;
+ l->prev = ll;
ll = ll->next;
}
l = l->next;
@@ -102,13 +104,20 @@ sortlocklist(MT_Lock *l)
t = ll = r;
} else {
ll->next = r;
+ r->prev = ll;
ll = ll->next;
}
r = r->next;
}
}
/* append rest of remaining list */
- ll->next = l ? l : r;
+ if (l) {
+ ll->next = l;
+ l->prev = ll;
+ } else {
+ ll->next = r;
+ r->prev = ll;
+ }
return t;
}
@@ -143,7 +152,9 @@ GDKlockstatistics(int what)
return;
}
GDKlocklist = sortlocklist(GDKlocklist);
- fprintf(stderr, "lock
name\tcount\tcontention\tsleep\tlocked\t(un)locker\tthread\n");
+ fprintf(stderr, "%-18s\t%s\t%s\t%s\t%s\t%s\t%s\n",
+ "lock name", "count", "content", "sleep",
+ "locked", "locker", "thread");
for (l = GDKlocklist; l; l = l->next) {
n++;
if (what == 0 ||
diff --git a/gdk/gdk_system.h b/gdk/gdk_system.h
--- a/gdk/gdk_system.h
+++ b/gdk/gdk_system.h
@@ -212,6 +212,9 @@ gdk_export int MT_join_thread(MT_Id t);
while (ATOMIC_TAS(&GDKlocklistlock) != 0) \
; \
(l)->next = GDKlocklist; \
+ (l)->prev = NULL; \
+ if (GDKlocklist) \
+ GDKlocklist->prev = (l); \
GDKlocklist = (l); \
ATOMIC_CLEAR(&GDKlocklistlock); \
} \
@@ -230,16 +233,17 @@ gdk_export int MT_join_thread(MT_Id t);
/* SQL storage allocator, and hence we have no control */ \
/* over when the lock is destroyed and the memory freed */ \
if (strncmp((l)->name, "sa_", 3) != 0) { \
- MT_Lock * volatile _p; \
while (ATOMIC_TAS(&GDKlocklistlock) != 0) \
; \
- for (_p = GDKlocklist; _p; _p = _p->next) \
- assert(_p != (l)); \
+ if (GDKlocklist) \
+ GDKlocklist->prev = (l); \
(l)->next = GDKlocklist; \
+ (l)->prev = NULL; \
GDKlocklist = (l); \
ATOMIC_CLEAR(&GDKlocklistlock); \
} else { \
(l)->next = NULL; \
+ (l)->prev = NULL; \
} \
} while (0)
@@ -250,14 +254,14 @@ gdk_export int MT_join_thread(MT_Id t);
/* SQL storage allocator, and hence we have no control */ \
/* over when the lock is destroyed and the memory freed */ \
if (strncmp((l)->name, "sa_", 3) != 0) { \
- MT_Lock * volatile *_p; \
while (ATOMIC_TAS(&GDKlocklistlock) != 0) \
; \
- for (_p = &GDKlocklist; *_p; _p = &(*_p)->next) \
- if ((l) == *_p) { \
- *_p = (l)->next; \
- break; \
- } \
+ if ((l)->next) \
+ (l)->next->prev = (l)->prev; \
+ if ((l)->prev) \
+ (l)->prev->next = (l)->next; \
+ else if (GDKlocklist == (l)) \
+ GDKlocklist = (l)->next; \
ATOMIC_CLEAR(&GDKlocklistlock); \
ATOMIC_DESTROY(&(l)->contention); \
ATOMIC_DESTROY(&(l)->sleep); \
@@ -285,7 +289,8 @@ typedef struct MT_Lock {
size_t count;
ATOMIC_TYPE contention;
ATOMIC_TYPE sleep;
- struct MT_Lock * volatile next;
+ struct MT_Lock *volatile next;
+ struct MT_Lock *volatile prev;
const char *locker;
const char *thread;
#endif
@@ -383,7 +388,8 @@ typedef struct MT_Lock {
size_t count;
ATOMIC_TYPE contention;
ATOMIC_TYPE sleep;
- struct MT_Lock * volatile next;
+ struct MT_Lock *volatile next;
+ struct MT_Lock *volatile prev;
const char *locker;
const char *thread;
#endif
_______________________________________________
checkin-list mailing list
[email protected]
https://www.monetdb.org/mailman/listinfo/checkin-list