Beispiel #1
0
/* select a worker to pull from */
struct thorium_worker *thorium_worker_pool_select_worker_for_message(struct thorium_worker_pool *pool)
{
    int index;
    int i;
    int score;
    struct thorium_worker *worker;
    int attempts;
    struct thorium_worker *best_worker;
    int best_score;
#ifdef THORIUM_WORKER_POOL_USE_COUNT_CACHE
    int best_index;

    best_index = -1;
#endif
    best_score = 0;
    best_worker = NULL;

    i = 0;
    attempts = THORIUM_WORKER_POOL_MESSAGE_SCHEDULING_WINDOW;

    /* select thet worker with the most messages in the window.
     */
    while (i < attempts) {

        index = pool->worker_for_message;
        pool->worker_for_message = thorium_worker_pool_next_worker(pool, index);
        worker = thorium_worker_pool_get_worker(pool, index);
#ifdef THORIUM_WORKER_POOL_USE_COUNT_CACHE
        score = thorium_worker_pool_get_cached_value(pool, index);
#else
        score = -1;
#endif

        /* Update the cache.
         * This is expensive because it will touch the cache line.
         * Only the worker is increasing the number of messages, and
         * only the worker pool is decreasing it.
         * As long as the cached value is greater than 0, then there is
         * definitely something to pull without the need
         * to break the CPU cache line
         *
         */
        /* always update cache because otherwise there will be
         * starvation
         */
        if (1 || score == 0) {
            score = thorium_worker_get_message_production_score(worker);
#ifdef THORIUM_WORKER_POOL_USE_COUNT_CACHE
            thorium_worker_pool_set_cached_value(pool, index, score);
#endif
        }

        if (best_worker == NULL || score > best_score) {
            best_worker = worker;
            best_score = score;
#ifdef THORIUM_WORKER_POOL_USE_COUNT_CACHE
            best_index = index;
#endif
        }

        ++i;
    }

#ifdef THORIUM_WORKER_POOL_USE_COUNT_CACHE
    /* Update the cached value for the winning worker to have an
     * accurate value for this worker.
     */
    core_vector_set_int(&pool->message_count_cache, best_index, best_score - 1);
#endif

    return best_worker;
}
Beispiel #2
0
int thorium_balancer_select_worker_least_busy(
                struct thorium_balancer *self, int *worker_score)
{
    int to_check;
    int score;
    int best_score;
    struct thorium_worker *worker;
    struct thorium_worker *best_worker;
    int selected_worker;

#if 0
    int last_worker_score;
#endif

#ifdef THORIUM_WORKER_DEBUG
    int tag;
    int destination;
    struct thorium_message *message;
#endif

    best_worker = NULL;
    best_score = 99;

    to_check = THORIUM_SCHEDULER_WORK_SCHEDULING_WINDOW;

    while (to_check--) {

        /*
         * get the worker to test for this iteration.
         */
        worker = thorium_worker_pool_get_worker(self->pool, self->worker_for_work);

        score = thorium_worker_get_epoch_load(worker);

#ifdef THORIUM_WORKER_POOL_DEBUG_ISSUE_334
        if (score >= THORIUM_WORKER_WARNING_THRESHOLD
                        && (self->last_scheduling_warning == 0
                             || score >= self->last_scheduling_warning + THORIUM_WORKER_WARNING_THRESHOLD_STRIDE)) {
            printf("Warning: node %d worker %d has a scheduling score of %d\n",
                            thorium_node_name(thorium_worker_pool_get_node(self->pool)),
                            self->worker_for_work, score);

            self->last_scheduling_warning = score;
        }
#endif

        /* if the worker is not busy and it has no work to do,
         * select it right away...
         */
        if (score == 0) {
            best_worker = worker;
            best_score = 0;
            break;
        }

        /* Otherwise, test the worker
         */
        if (best_worker == NULL || score < best_score) {
            best_worker = worker;
            best_score = score;
        }

        /*
         * assign the next worker
         */
        self->worker_for_work = thorium_worker_pool_next_worker(self->pool, self->worker_for_work);
    }

#ifdef THORIUM_WORKER_POOL_DEBUG
    message = biosal_work_message(work);
    tag = thorium_message_action(message);
    destination = thorium_message_destination(message);

    if (tag == ACTION_ASK_TO_STOP) {
        printf("DEBUG dispatching ACTION_ASK_TO_STOP for actor %d to worker %d\n",
                        destination, *start);
    }


#endif

    selected_worker = self->worker_for_work;

    /*
     * assign the next worker
     */
    self->worker_for_work = thorium_worker_pool_next_worker(self->pool, self->worker_for_work);

    *worker_score = best_score;
    /* This is a best effort algorithm
     */
    return selected_worker;
}