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,
};
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)

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 {
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;
}