From 019ab99eccd7d936a354a68a8a80d60b2ddf249f Mon Sep 17 00:00:00 2001 From: Cory McWilliams Date: Sat, 15 Jan 2022 17:40:24 +0000 Subject: [PATCH] Trying to better understand import/export leaks. Possibly cleaned up after tasks better, but mostly just tweaked counters. git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@3762 ed5197a5-7fde-0310-b194-c3ffbd925b24 --- src/ssb.c | 2 +- src/task.c | 145 +++++++++++++++++++++++++++++------------------------ 2 files changed, 81 insertions(+), 66 deletions(-) diff --git a/src/ssb.c b/src/ssb.c index c29489f4..087402b2 100644 --- a/src/ssb.c +++ b/src/ssb.c @@ -1516,7 +1516,7 @@ static void _tf_ssb_trace_timer(uv_timer_t* timer) ssb->broadcasts_changed_count, }; - tf_trace_counter(ssb->trace, "lists", _countof(values), names, values); + tf_trace_counter(ssb->trace, "ssb", _countof(values), names, values); } tf_ssb_t* tf_ssb_create(uv_loop_t* loop, JSContext* context, sqlite3* db, const char* secrets_path) diff --git a/src/task.c b/src/task.c index 40ab05eb..e1ceea34 100644 --- a/src/task.c +++ b/src/task.c @@ -40,7 +40,8 @@ typedef struct _import_record_t import_record_t; typedef struct _task_child_node_t task_child_node_t; -typedef struct _task_child_node_t { +typedef struct _task_child_node_t +{ taskid_t id; tf_taskstub_t* stub; task_child_node_t* next; @@ -48,19 +49,22 @@ typedef struct _task_child_node_t { typedef struct _script_export_t script_export_t; -typedef struct _script_export_t { +typedef struct _script_export_t +{ const char* name; JSValue value; script_export_t* next; } script_export_t; typedef struct _promise_t promise_t; -typedef struct _promise_t { +typedef struct _promise_t +{ promiseid_t id; JSValue values[3]; } promise_t; -typedef struct _tf_task_t { +typedef struct _tf_task_t +{ taskid_t _nextTask; task_child_node_t* _children; int _child_count; @@ -90,6 +94,7 @@ typedef struct _tf_task_t { int _promise_count; promiseid_t _nextPromise; uv_loop_t _loop; + uv_timer_t trace_timer; export_record_t** _exports; int _export_count; @@ -108,7 +113,8 @@ typedef struct _tf_task_t { const char* _args; } tf_task_t; -typedef struct _export_record_t { +typedef struct _export_record_t +{ taskid_t _taskid; exportid_t _export_id; JSValue _function; @@ -154,7 +160,8 @@ static JSValue _tf_task_executeSource(tf_task_t* task, const char* source, const static tf_taskstub_t* _tf_task_get_stub(tf_task_t* task, taskid_t id); static void _tf_task_release_export(tf_taskstub_t* stub, exportid_t exportId); -typedef struct _import_record_t { +typedef struct _import_record_t +{ tf_task_t* _owner; JSValue _function; exportid_t _export; @@ -195,57 +202,44 @@ static import_record_t** _tf_task_find_import(tf_task_t* task, taskid_t task_id, return it; } -static void _tf_task_trace_imports(tf_task_t* task) -{ - tf_trace_counter(task->_trace, "imports", 1, (const char*[]) { "count" }, (int64_t[]) { task->_import_count }); -} - -static void _import_record_release(import_record_t** import) +static bool _import_record_release(import_record_t** import) { JSContext* context = (*import)->_owner->_context; tf_task_t* task = (*import)->_owner; import_record_t* record = *import; - if (--record->_useCount > 0) + if (--record->_useCount == 0) { - return; + JS_SetOpaque(record->_function, NULL); + JS_FreeValue(context, record->_function); + record->_function = JS_UNDEFINED; + _tf_task_release_export(_tf_task_get_stub(task, record->_task), record->_export); + + int index = import - task->_imports; + if (task->_import_count - index) + { + memmove(import, import + 1, sizeof(import_record_t*) * (task->_import_count - index - 1)); + } + task->_import_count--; + + free(record); + return false; } - - JS_SetOpaque(record->_function, NULL); - JS_FreeValue(context, record->_function); - record->_function = JS_UNDEFINED; - _tf_task_release_export(_tf_task_get_stub(task, record->_task), record->_export); - - int index = import - task->_imports; - memmove(import, import + 1, sizeof(import_record_t*) * (task->_import_count - index - 1)); - task->_import_count--; - _tf_task_trace_imports(task); - - free(record); + return true; } static void _import_record_release_for_task(tf_task_t* task, taskid_t task_id) { - bool any = false; for (int i = 0; i < task->_import_count; i++) { if (task->_imports[i]->_task == task_id) { - _import_record_release(&task->_imports[i]); - any = true; + while (!_import_record_release(&task->_imports[i])) + { + } --i; } } - - if (any) - { - _tf_task_trace_imports(task); - } -} - -static void _tf_task_trace_exports(tf_task_t* task) -{ - tf_trace_counter(task->_trace, "exports", 1, (const char*[]) { "count" }, (int64_t[]) { task->_export_count }); } static int _export_compare(const void* a, const void* b) @@ -264,23 +258,16 @@ static int _export_compare(const void* a, const void* b) static void _export_record_release_for_task(tf_task_t* task, taskid_t task_id) { - bool any = false; for (int i = 0; i < task->_export_count; i++) { if (task->_exports[i]->_taskid == task_id) { - if (_export_record_release(task, &task->_exports[i])) + while (!_export_record_release(task, &task->_exports[i])) { - any = true; - i--; } + i--; } } - - if (any) - { - _tf_task_trace_exports(task); - } } void tf_task_send_error_to_parent(tf_task_t* task, JSValue error) @@ -420,6 +407,10 @@ static JSValue _import_call(JSContext* context, JSValueConst func_obj, JSValueCo static export_record_t** _task_get_export(tf_task_t* task, exportid_t export_id) { + if (!task->_export_count) + { + return NULL; + } export_record_t** it = bsearch(&export_id, task->_exports, task->_export_count, sizeof(export_record_t*), _export_compare); return it; } @@ -660,7 +651,6 @@ exportid_t tf_task_export_function(tf_task_t* task, tf_taskstub_t* to, JSValue f } task->_exports[index] = export; task->_export_count++; - _tf_task_trace_exports(task); } if (export) @@ -683,7 +673,8 @@ static void _tf_task_release_export(tf_taskstub_t* stub, exportid_t exportId) } } -static JSValue _tf_task_trace(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv){ +static JSValue _tf_task_trace(JSContext* context, JSValueConst this_val, int argc, JSValueConst* argv) +{ tf_task_t* task = JS_GetContextOpaque(context); if (!task->_trace) { @@ -1103,11 +1094,6 @@ static promise_t* _tf_task_find_promise(tf_task_t* task, promiseid_t id) return it ? it : NULL; } -static void _tf_task_trace_promises(tf_task_t* task) -{ - tf_trace_counter(task->_trace, "promises", 1, (const char*[]) { "count" }, (int64_t[]) { task->_promise_count }); -} - static void _tf_task_free_promise(tf_task_t* task, promiseid_t id) { promise_t* it = bsearch((void*)(intptr_t)id, task->_promises, task->_promise_count, sizeof(promise_t), _promise_compare); @@ -1116,7 +1102,6 @@ static void _tf_task_free_promise(tf_task_t* task, promiseid_t id) int index = it - task->_promises; memmove(it, it + 1, sizeof(promise_t) * (task->_promise_count - index - 1)); task->_promise_count--; - _tf_task_trace_promises(task); } } @@ -1141,7 +1126,6 @@ JSValue tf_task_allocate_promise(tf_task_t* task, promiseid_t* out_promise) } task->_promises[index] = promise; task->_promise_count++; - _tf_task_trace_promises(task); *out_promise = promiseId; return promise.values[0]; } @@ -1187,11 +1171,6 @@ JSValue tf_task_get_promise(tf_task_t* task, promiseid_t promise) return it ? it->values[0] : JS_NULL; } -static void _tf_task_trace_children(tf_task_t* task) -{ - tf_trace_counter(task->_trace, "child_tasks", 1, (const char*[]) { "count" }, (int64_t[]) { task->_child_count }); -} - taskid_t tf_task_allocate_task_id(tf_task_t* task, tf_taskstub_t* stub) { taskid_t id = 0; @@ -1208,7 +1187,6 @@ taskid_t tf_task_allocate_task_id(tf_task_t* task, tf_taskstub_t* stub) }; task->_children = node; task->_child_count++; - _tf_task_trace_children(task); return id; } @@ -1226,7 +1204,6 @@ void tf_task_remove_child(tf_task_t* task, tf_taskstub_t* child) *it = node->next; free(node); task->_child_count--; - _tf_task_trace_children(task); break; } } @@ -1259,6 +1236,26 @@ static void _tf_task_promise_rejection_tracker(JSContext* context, JSValueConst } } +static void _tf_task_trace_timer(uv_timer_t* timer) +{ + tf_task_t* task = timer->data; + const char* k_names[] = + { + "child_tasks", + "imports", + "exports", + "promises", + }; + int64_t values[] = + { + task->_child_count, + task->_import_count, + task->_export_count, + task->_promise_count, + }; + tf_trace_counter(task->_trace, "task", sizeof(k_names) / sizeof(*k_names), k_names, values); +} + tf_task_t* tf_task_create() { tf_task_t* task = malloc(sizeof(tf_task_t)); @@ -1282,6 +1279,10 @@ tf_task_t* tf_task_create() task->_loadedFiles = JS_NewObject(task->_context); uv_loop_init(&task->_loop); task->_loop.data = task; + task->trace_timer.data = task; + uv_timer_init(&task->_loop, &task->trace_timer); + uv_timer_start(&task->trace_timer, _tf_task_trace_timer, 100, 100); + uv_unref((uv_handle_t*)&task->trace_timer); return task; } @@ -1396,6 +1397,11 @@ JSContext* tf_task_get_context(tf_task_t* task) return task->_context; } +static void _tf_task_on_handle_close(uv_handle_t* handle) +{ + handle->data = NULL; +} + void tf_task_destroy(tf_task_t* task) { for (int i = 0; i < task->_import_count; i++) @@ -1461,6 +1467,16 @@ void tf_task_destroy(tf_task_t* task) sqlite3_close(task->_db); } + if (task->trace_timer.data && !uv_is_closing((uv_handle_t*)&task->trace_timer)) + { + uv_close((uv_handle_t*)&task->trace_timer, _tf_task_on_handle_close); + } + + while (task->trace_timer.data) + { + uv_run(&task->_loop, UV_RUN_ONCE); + } + if (uv_loop_close(&task->_loop) != 0) { uv_print_all_handles(&task->_loop, stdout); @@ -1492,7 +1508,6 @@ JSValue tf_task_add_import(tf_task_t* task, taskid_t stub_id, exportid_t export_ } task->_imports[index] = import; task->_import_count++; - _tf_task_trace_imports(task); return function; }