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
This commit is contained in:
Cory McWilliams 2022-01-15 17:40:24 +00:00
parent c40a513876
commit 019ab99ecc
2 changed files with 81 additions and 66 deletions

View File

@ -1516,7 +1516,7 @@ static void _tf_ssb_trace_timer(uv_timer_t* timer)
ssb->broadcasts_changed_count, 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) tf_ssb_t* tf_ssb_create(uv_loop_t* loop, JSContext* context, sqlite3* db, const char* secrets_path)

View File

@ -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 task_child_node_t;
typedef struct _task_child_node_t { typedef struct _task_child_node_t
{
taskid_t id; taskid_t id;
tf_taskstub_t* stub; tf_taskstub_t* stub;
task_child_node_t* next; 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 script_export_t;
typedef struct _script_export_t { typedef struct _script_export_t
{
const char* name; const char* name;
JSValue value; JSValue value;
script_export_t* next; script_export_t* next;
} script_export_t; } script_export_t;
typedef struct _promise_t promise_t; typedef struct _promise_t promise_t;
typedef struct _promise_t { typedef struct _promise_t
{
promiseid_t id; promiseid_t id;
JSValue values[3]; JSValue values[3];
} promise_t; } promise_t;
typedef struct _tf_task_t { typedef struct _tf_task_t
{
taskid_t _nextTask; taskid_t _nextTask;
task_child_node_t* _children; task_child_node_t* _children;
int _child_count; int _child_count;
@ -90,6 +94,7 @@ typedef struct _tf_task_t {
int _promise_count; int _promise_count;
promiseid_t _nextPromise; promiseid_t _nextPromise;
uv_loop_t _loop; uv_loop_t _loop;
uv_timer_t trace_timer;
export_record_t** _exports; export_record_t** _exports;
int _export_count; int _export_count;
@ -108,7 +113,8 @@ typedef struct _tf_task_t {
const char* _args; const char* _args;
} tf_task_t; } tf_task_t;
typedef struct _export_record_t { typedef struct _export_record_t
{
taskid_t _taskid; taskid_t _taskid;
exportid_t _export_id; exportid_t _export_id;
JSValue _function; 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 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); 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; tf_task_t* _owner;
JSValue _function; JSValue _function;
exportid_t _export; 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; return it;
} }
static void _tf_task_trace_imports(tf_task_t* task) static bool _import_record_release(import_record_t** import)
{
tf_trace_counter(task->_trace, "imports", 1, (const char*[]) { "count" }, (int64_t[]) { task->_import_count });
}
static void _import_record_release(import_record_t** import)
{ {
JSContext* context = (*import)->_owner->_context; JSContext* context = (*import)->_owner->_context;
tf_task_t* task = (*import)->_owner; tf_task_t* task = (*import)->_owner;
import_record_t* record = *import; 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;
} }
return true;
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);
} }
static void _import_record_release_for_task(tf_task_t* task, taskid_t task_id) 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++) for (int i = 0; i < task->_import_count; i++)
{ {
if (task->_imports[i]->_task == task_id) if (task->_imports[i]->_task == task_id)
{ {
_import_record_release(&task->_imports[i]); while (!_import_record_release(&task->_imports[i]))
any = true; {
}
--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) 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) 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++) for (int i = 0; i < task->_export_count; i++)
{ {
if (task->_exports[i]->_taskid == task_id) 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) 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) 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); export_record_t** it = bsearch(&export_id, task->_exports, task->_export_count, sizeof(export_record_t*), _export_compare);
return it; 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->_exports[index] = export;
task->_export_count++; task->_export_count++;
_tf_task_trace_exports(task);
} }
if (export) 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); tf_task_t* task = JS_GetContextOpaque(context);
if (!task->_trace) 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; 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) 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); 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; int index = it - task->_promises;
memmove(it, it + 1, sizeof(promise_t) * (task->_promise_count - index - 1)); memmove(it, it + 1, sizeof(promise_t) * (task->_promise_count - index - 1));
task->_promise_count--; 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->_promises[index] = promise;
task->_promise_count++; task->_promise_count++;
_tf_task_trace_promises(task);
*out_promise = promiseId; *out_promise = promiseId;
return promise.values[0]; 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; 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 tf_task_allocate_task_id(tf_task_t* task, tf_taskstub_t* stub)
{ {
taskid_t id = 0; 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->_children = node;
task->_child_count++; task->_child_count++;
_tf_task_trace_children(task);
return id; return id;
} }
@ -1226,7 +1204,6 @@ void tf_task_remove_child(tf_task_t* task, tf_taskstub_t* child)
*it = node->next; *it = node->next;
free(node); free(node);
task->_child_count--; task->_child_count--;
_tf_task_trace_children(task);
break; 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* tf_task_create()
{ {
tf_task_t* task = malloc(sizeof(tf_task_t)); 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); task->_loadedFiles = JS_NewObject(task->_context);
uv_loop_init(&task->_loop); uv_loop_init(&task->_loop);
task->_loop.data = task; 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; return task;
} }
@ -1396,6 +1397,11 @@ JSContext* tf_task_get_context(tf_task_t* task)
return task->_context; 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) void tf_task_destroy(tf_task_t* task)
{ {
for (int i = 0; i < task->_import_count; i++) 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); 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) if (uv_loop_close(&task->_loop) != 0)
{ {
uv_print_all_handles(&task->_loop, stdout); 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->_imports[index] = import;
task->_import_count++; task->_import_count++;
_tf_task_trace_imports(task);
return function; return function;
} }