mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
mruby-task: optimize mrb_task struct memory footprint
reduces per-task memory usage by 8 bytes (6.2%) through: - removing priority_preemption field (always equals priority) - removing started flag (inferred from context status) - unifying wakeup_tick/join/mutex into single union old size: 128 bytes new size: 120 bytes all tests pass with no functionality changes. Co-authored-by: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -32,22 +32,27 @@ enum {
|
||||
|
||||
/*
|
||||
* Task structure - represents a single task in the scheduler
|
||||
*
|
||||
* Memory-optimized layout:
|
||||
* - Removed priority_preemption (always equals priority)
|
||||
* - Removed started flag (inferred from c.status != MRB_FIBER_CREATED)
|
||||
* - Unified wakeup_tick/join/mutex into single union (mutually exclusive)
|
||||
* Total savings: ~8 bytes per task
|
||||
*/
|
||||
typedef struct mrb_task {
|
||||
struct mrb_task *next; /* Linked list pointer */
|
||||
uint8_t priority; /* Initial priority (0-255, 0=highest) */
|
||||
uint8_t priority_preemption; /* Effective priority for preemption */
|
||||
volatile uint8_t timeslice; /* Remaining time slice ticks */
|
||||
uint8_t priority; /* Priority (0-255, 0=highest) */
|
||||
uint8_t status; /* Current status (TASKSTATUS enum) */
|
||||
uint8_t reason; /* Wait reason (TASKREASON enum) */
|
||||
uint8_t started; /* 1 if task has been started, 0 otherwise */
|
||||
volatile uint8_t timeslice; /* Remaining time slice ticks */
|
||||
mrb_value name; /* Optional task name */
|
||||
|
||||
/* Wait-specific data - mutually exclusive based on reason field */
|
||||
union {
|
||||
uint32_t wakeup_tick; /* Tick count to wake up (for sleep) */
|
||||
void *mutex; /* Mutex pointer (reserved) */
|
||||
};
|
||||
const struct mrb_task *join; /* Task being waited on (for join) */
|
||||
uint32_t wakeup_tick; /* Tick count to wake up (REASON_SLEEP) */
|
||||
const struct mrb_task *join; /* Task being waited on (REASON_JOIN) */
|
||||
void *mutex; /* Mutex pointer (REASON_MUTEX, reserved) */
|
||||
} wait;
|
||||
|
||||
mrb_value self; /* Ruby Task object reference */
|
||||
mrb_value result; /* Task return value */
|
||||
|
||||
@@ -167,7 +167,7 @@ q_insert_task(mrb_state *mrb, mrb_task *t)
|
||||
mrb_task *prev = NULL;
|
||||
|
||||
/* Find insertion point - insert before first task with lower priority */
|
||||
while (curr != NULL && curr->priority_preemption <= t->priority_preemption) {
|
||||
while (curr != NULL && curr->priority <= t->priority) {
|
||||
prev = curr;
|
||||
curr = curr->next;
|
||||
}
|
||||
@@ -280,12 +280,12 @@ wake_up_join_waiters(mrb_state *mrb, mrb_task *completed_task)
|
||||
mrb_task *curr = q_waiting_;
|
||||
while (curr != NULL) {
|
||||
mrb_task *next = curr->next;
|
||||
if (curr->reason == MRB_TASK_REASON_JOIN && curr->join == completed_task) {
|
||||
if (curr->reason == MRB_TASK_REASON_JOIN && curr->wait.join == completed_task) {
|
||||
mrb_task_disable_irq();
|
||||
q_delete_task(mrb, curr);
|
||||
curr->status = MRB_TASK_STATUS_READY;
|
||||
curr->reason = MRB_TASK_REASON_NONE;
|
||||
curr->join = NULL;
|
||||
curr->wait.join = NULL;
|
||||
q_insert_task(mrb, curr);
|
||||
mrb_task_enable_irq();
|
||||
}
|
||||
@@ -324,9 +324,8 @@ execute_task(mrb_state *mrb, mrb_task *t)
|
||||
mrb->c = &t->c;
|
||||
|
||||
/* If task hasn't started yet, pop dummy callinfo */
|
||||
if (!t->started) {
|
||||
if (t->c.status == MRB_FIBER_CREATED) {
|
||||
t->c.ci--;
|
||||
t->started = 1;
|
||||
}
|
||||
|
||||
/* Clear switching flag */
|
||||
@@ -404,7 +403,7 @@ mrb_tick(mrb_state *mrb)
|
||||
next = curr->next;
|
||||
|
||||
if (curr->reason == MRB_TASK_REASON_SLEEP) {
|
||||
if ((int32_t)(curr->wakeup_tick - tick_) <= 0) {
|
||||
if ((int32_t)(curr->wait.wakeup_tick - tick_) <= 0) {
|
||||
/* Time to wake up */
|
||||
q_delete_task(mrb, curr);
|
||||
curr->status = MRB_TASK_STATUS_READY;
|
||||
@@ -412,8 +411,8 @@ mrb_tick(mrb_state *mrb)
|
||||
q_insert_task(mrb, curr);
|
||||
switching_ = TRUE;
|
||||
}
|
||||
else if (curr->wakeup_tick < next_wakeup) {
|
||||
next_wakeup = curr->wakeup_tick;
|
||||
else if (curr->wait.wakeup_tick < next_wakeup) {
|
||||
next_wakeup = curr->wait.wakeup_tick;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -515,11 +514,11 @@ sleep_us_impl(mrb_state *mrb, mrb_int usec)
|
||||
t->status = MRB_TASK_STATUS_WAITING;
|
||||
t->reason = MRB_TASK_REASON_SLEEP;
|
||||
/* Convert microseconds to ticks (tick unit is in milliseconds) */
|
||||
t->wakeup_tick = tick_ + USEC_TO_TICKS(usec);
|
||||
t->wait.wakeup_tick = tick_ + USEC_TO_TICKS(usec);
|
||||
|
||||
/* Update next wakeup time if this task wakes earlier */
|
||||
if ((int32_t)(t->wakeup_tick - wakeup_tick_) < 0) {
|
||||
wakeup_tick_ = t->wakeup_tick;
|
||||
if ((int32_t)(t->wait.wakeup_tick - wakeup_tick_) < 0) {
|
||||
wakeup_tick_ = t->wait.wakeup_tick;
|
||||
}
|
||||
|
||||
q_insert_task(mrb, t);
|
||||
@@ -650,7 +649,6 @@ mrb_task_s_new(mrb_state *mrb, mrb_value self)
|
||||
/* Allocate and initialize task */
|
||||
t = task_alloc(mrb);
|
||||
t->priority = (uint8_t)priority;
|
||||
t->priority_preemption = (uint8_t)priority;
|
||||
t->status = MRB_TASK_STATUS_READY;
|
||||
t->reason = MRB_TASK_REASON_NONE;
|
||||
t->name = name_val;
|
||||
@@ -986,7 +984,6 @@ mrb_task_set_priority(mrb_state *mrb, mrb_value self)
|
||||
|
||||
mrb_task_disable_irq();
|
||||
t->priority = (uint8_t)priority;
|
||||
t->priority_preemption = (uint8_t)priority;
|
||||
|
||||
/* Re-sort in queue if task is ready */
|
||||
if (t->status == MRB_TASK_STATUS_READY || t->status == MRB_TASK_STATUS_RUNNING) {
|
||||
@@ -1105,7 +1102,7 @@ mrb_task_join(mrb_state *mrb, mrb_value self)
|
||||
q_delete_task(mrb, current);
|
||||
current->status = MRB_TASK_STATUS_WAITING;
|
||||
current->reason = MRB_TASK_REASON_JOIN;
|
||||
current->join = t;
|
||||
current->wait.join = t;
|
||||
q_insert_task(mrb, current);
|
||||
mrb_task_enable_irq();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user