Needs more work, but several experiments that make things more responsive under load.

git-svn-id: https://www.unprompted.com/svn/projects/tildefriends/trunk@3783 ed5197a5-7fde-0310-b194-c3ffbd925b24
This commit is contained in:
2022-01-22 20:13:14 +00:00
parent 0f03701043
commit b2a552b3e0
9 changed files with 128 additions and 100 deletions

View File

@ -99,6 +99,9 @@ typedef struct _tf_task_t
uint64_t last_hrtime;
uint64_t last_idle_time;
uv_idle_t idle;
uv_prepare_t prepare;
export_record_t** _exports;
int _export_count;
exportid_t _nextExport;
@ -349,7 +352,6 @@ int tf_task_execute(tf_task_t* task, const char* fileName)
executed = true;
}
JS_FreeValue(task->_context, result);
tf_task_run_jobs(task);
free((void*)source);
}
else
@ -469,7 +471,6 @@ JSValue _task_invokeExport_internal(tf_taskstub_t* from, tf_task_t* to, exportid
result = JS_Call(to->_context, function, this_val, length - 1, argument_array);
tf_trace_end(to->_trace);
tf_util_report_error(to->_context, result);
tf_task_run_jobs(to);
JS_FreeValue(to->_context, this_val);
for (int i = 0; i < length - 1; i++)
@ -535,8 +536,6 @@ static void _forward_promise(tf_task_t* from, tf_taskstub_t* to, promiseid_t pro
JS_FreeValue(from->_context, promise_catch);
JS_FreeValue(from->_context, then_handler);
JS_FreeValue(from->_context, catch_handler);
tf_task_run_jobs(from);
}
static void _tf_task_sendPromiseResolve(tf_task_t* from, tf_taskstub_t* to, promiseid_t promise, JSValue result)
@ -1000,7 +999,6 @@ JSValue _tf_task_require(JSContext* context, JSValueConst this_val, int argc, JS
JS_SetPropertyStr(task->_context, global, "exports", JS_DupValue(task->_context, exports));
JSValue eval = JS_Eval(task->_context, source, strlen(source), path, 0);
tf_util_report_error(task->_context, eval);
tf_task_run_jobs(task);
if (JS_IsError(task->_context, eval) ||
JS_IsException(eval))
{
@ -1040,10 +1038,6 @@ static JSValue _tf_task_executeSource(tf_task_t* task, const char* source, const
{
snprintf(task->_scriptName, sizeof(task->_scriptName), "%s", name);
}
if (!JS_IsException(result))
{
tf_task_run_jobs(task);
}
tf_trace_end(task->_trace);
return result;
}
@ -1079,7 +1073,6 @@ JSValue _tf_task_sandbox_require(JSContext* context, JSValueConst this_val, int
tf_util_report_error(context, result);
JS_SetPropertyStr(context, global, "exports", oldExports);
JS_FreeValue(context, global);
tf_task_run_jobs(task);
free(source);
return exports;
}
@ -1094,7 +1087,6 @@ JSValue _tf_task_sandbox_require(JSContext* context, JSValueConst this_val, int
tf_util_report_error(context, result);
JS_SetPropertyStr(context, global, "exports", oldExports);
JS_FreeValue(context, global);
tf_task_run_jobs(task);
return exports;
}
else
@ -1181,7 +1173,6 @@ void tf_task_resolve_promise(tf_task_t* task, promiseid_t promise, JSValue value
JS_FreeValue(task->_context, it->values[2]);
JS_FreeValue(task->_context, result);
_tf_task_free_promise(task, promise);
tf_task_run_jobs(task);
}
else
{
@ -1212,7 +1203,6 @@ void tf_task_reject_promise(tf_task_t* task, promiseid_t promise, JSValue value)
JS_FreeValue(task->_context, it->values[2]);
JS_FreeValue(task->_context, result);
_tf_task_free_promise(task, promise);
tf_task_run_jobs(task);
}
}
@ -1314,6 +1304,54 @@ static void _tf_task_trace_timer(uv_timer_t* timer)
tf_trace_counter(task->_trace, "task", sizeof(k_names) / sizeof(*k_names), k_names, values);
}
static void _tf_task_run_jobs_idle(uv_idle_t* idle);
static void _tf_task_run_jobs_prepare(uv_prepare_t* prepare);
static bool _tf_task_run_jobs(tf_task_t* task)
{
if (JS_IsJobPending(task->_runtime))
{
JSContext* context = NULL;
int r = JS_ExecutePendingJob(task->_runtime, &context);
JSValue result = JS_GetException(context);
if (context)
{
tf_util_report_error(context, result);
}
if (r < 0)
{
js_std_dump_error(context);
}
else
{
return r != 0;
}
}
return 0;
}
static void _tf_task_run_jobs_idle(uv_idle_t* idle)
{
tf_task_t* task = idle->data;
if (!_tf_task_run_jobs(task))
{
/* No more jobs. Don't try again as actively. */
uv_idle_stop(&task->idle);
uv_prepare_start(&task->prepare, _tf_task_run_jobs_prepare);
}
}
static void _tf_task_run_jobs_prepare(uv_prepare_t* prepare)
{
tf_task_t* task = prepare->data;
if (_tf_task_run_jobs(task))
{
/* More jobs. We can run again immediately. */
uv_idle_start(&task->idle, _tf_task_run_jobs_idle);
uv_prepare_stop(&task->prepare);
}
}
tf_task_t* tf_task_create()
{
tf_task_t* task = malloc(sizeof(tf_task_t));
@ -1342,6 +1380,11 @@ tf_task_t* tf_task_create()
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);
task->idle.data = task;
uv_idle_init(&task->_loop, &task->idle);
task->prepare.data = task;
uv_prepare_init(&task->_loop, &task->prepare);
uv_idle_start(&task->idle, _tf_task_run_jobs_idle);
return task;
}
@ -1531,8 +1574,12 @@ void tf_task_destroy(tf_task_t* task)
{
uv_close((uv_handle_t*)&task->trace_timer, _tf_task_on_handle_close);
}
uv_close((uv_handle_t*)&task->idle, _tf_task_on_handle_close);
uv_close((uv_handle_t*)&task->prepare, _tf_task_on_handle_close);
while (task->trace_timer.data)
while (task->trace_timer.data ||
task->idle.data ||
task->prepare.data)
{
uv_run(&task->_loop, UV_RUN_ONCE);
}
@ -1587,28 +1634,6 @@ tf_task_t* tf_task_get(JSContext* context)
return JS_GetContextOpaque(context);
}
void tf_task_run_jobs(tf_task_t* task)
{
while (JS_IsJobPending(task->_runtime))
{
JSContext* context = NULL;
int r = JS_ExecutePendingJob(task->_runtime, &context);
JSValue result = JS_GetException(context);
if (context)
{
tf_util_report_error(context, result);
}
if (r < 0)
{
js_std_dump_error(context);
}
else if (r == 0)
{
break;
}
}
}
void tf_task_send_promise_message(tf_task_t* from, tf_taskstub_t* to, tf_task_message_t type, promiseid_t promise, JSValue payload)
{
_tf_task_sendPromiseMessage(from, to, type, promise, payload);