Быстрый и (в идеале) нить безопасный объект бассейн в C


У меня есть вспомогательные структуры называют скрэбом, что расчет 'Блокнот'. Вообще, мне нужен только один из этих объектов, но если у меня есть вложенные расчетов мне нужна одна царапина на уровень вложенности. И если я хочу сделать расчет потокобезопасным, то каждый поток будет нужен один или несколько объектов царапины.

Для простых случаев Singleton-объект царапины работает отлично и я могу достичь 38 шагов в секунду. Если я изменить с помощью одноэлементного просто инстанцирования объекта нуля каждый раз, когда я упасть до 10 шагов в секунду.

С помощью многопоточной версии на бассейн ниже (закомментировав мьютекс блокирует и разблокирует) у меня как раз до 35-38ish шагов в секунду. Но потокобезопасной версии, перечисленные ниже сшибает меня с ног до 16 шагов в секунду. Итак, для того, чтобы продевать стоит, мне придется преодолеть, что первоначальный удар по производительности.

Я теоретически думаю должно быть два ядра способны почти безубыток и 3 или более, должны быть в состоянии сделать стоимость замок стоит, но я не пробовал, что еще.

Любые предложения, комментарии, критику с благодарностью.

typedef struct Pool {
    Scratch** scratches;
    int n;
    int i;
    pthread_mutex_t mutex;
} Pool;

Pool* pool_;

Pool* AEPoolCreate() {
    Pool* pool = (Pool*)malloc(sizeof(Pool));
    pool->scratches = (Scratch**)malloc(sizeof(Scratch*));
    pool->scratches[0] = AEScratchCreate();
    pool->n = 1;
    pool->i = 0;
    pthread_mutex_init(&pool->mutex, NULL);
    return pool;
}
Scratch* AEPoolGet(Pool* pool) {
    pthread_mutex_lock(&pool->mutex);
    if (pool->i == pool->n) {
        pool->n *= 2;
        printf("[ Pool ===================== ]\n");
        printf("   increased to a size of %d\n", pool->n);
        printf("[ =========================== ]\n\n");
        pool->scratches = (Scratch**)realloc(pool->scratches, sizeof(Scratch*)*pool->n);
        for (int i=pool->i;i<pool->n;i++)
            pool->scratches[i] = AEScratchCreate();
    }
    Scratch* scratch = pool->scratches[pool->i++];
    pthread_mutex_unlock(&pool->mutex);
    return scratch;
}
void AEPoolPut(Pool* pool, Scratch* scratch) {
    pthread_mutex_lock(&pool->mutex);
    scratch->cp = 0;
    scratch->vp = 0;
    scratch->sp = 0;
    pool->i--;
    pool->scratches[pool->i] = scratch;
    pthread_mutex_unlock(&pool->mutex);
}

Здесь является объектом нуля, как просил:

// Scratch =
typedef struct Scratch {
    Obj* stack;
    byte sp;
    byte cp;
    byte vp;
} Scratch;
Scratch* AEScratchCreate() {
    Scratch* scratch = (Scratch*)malloc(sizeof(Scratch));
    scratch->stack = (Obj*)malloc(sizeof(Obj)*10);
    scratch->cp = 0;
    scratch->vp = 0;
    scratch->sp = 0;
    return scratch;
}
void AEScratchRelease(Scratch* scratch) {
    if (scratch == 0) return;
    free(scratch->stack);
    free(scratch);
}

// Dim =====
typedef union {
    long n;
    double x;
    void* p;
} Dim;

// Obj =====
typedef struct {
    Dim a;
    Dim b;
    Dim c;
    //  byte type;
} Obj;


164
4
задан 8 апреля 2018 в 01:04 Источник Поделиться
Комментарии
1 ответ

Одно небольшое улучшение было бы не получить Блокировку в AEPoolPut вплоть до доступа pool (т. е., очистить поля в scratch перед приобретением замка).

На самом деле там нет ничего еще я вижу, что можно изменить здесь, что бы помочь (если вообще количество царапин требуется более или менее стабильным, так что AEPoolGet быстро достигнет точки, где она не будет выделять никаких больше царапин. Есть некоторые хитрости, которые могут применяться, если вы постоянно расти количество бассейнов.

В коде темы, что использовать это можно реализовать какой-то механизм-нить локальное кэширование нуля, так что если поток заканчивает использование объекта поцарапать его повесят на него локально и использовать его. Это позволит обойти весь этот код. Если есть слишком многие из этих "свободных" объекты нуля, вы можете вернуть излишки обратно в бассейн. В зависимости от вашего использования, вам может понадобиться кэш одним объектом нуля.

1
ответ дан 9 апреля 2018 в 03:04 Источник Поделиться