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:
parent
c40a513876
commit
019ab99ecc
@ -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)
|
||||
|
127
src/task.c
127
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--;
|
||||
_tf_task_trace_imports(task);
|
||||
|
||||
free(record);
|
||||
return false;
|
||||
}
|
||||
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--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user