1. Reduce the number of locks with dirty read first, and then try to lock sc and real read. QPS:360k -> 380k.

2. memory alignment. QPS:380k -> 400k.
This commit is contained in:
fengbojiang 2023-04-14 14:37:15 +08:00
parent 4af5a643fb
commit 3cd0ab86b6
4 changed files with 60 additions and 36 deletions

View File

@ -81,14 +81,17 @@ static __thread struct ff_kevent_args *kevent_args = NULL;
} \
args = name##_args;
/* Dirty read first, and then try to lock sc and real read. */
#define ACQUIRE_ZONE_LOCK(exp) do { \
while (1) { \
while (sc->status != exp) { \
rte_pause(); \
} \
rte_spinlock_lock(&sc->lock); \
if (sc->status == exp) { \
break; \
} \
rte_spinlock_unlock(&sc->lock); \
rte_pause(); \
} \
} while (0)
@ -1545,7 +1548,8 @@ kevent(int kq, const struct kevent *changelist, int nchanges,
args->kq = kq;
args->timeout = (struct timespec *)timeout;
rte_spinlock_lock(&sc->lock);
ACQUIRE_ZONE_LOCK(FF_SC_IDLE);
//rte_spinlock_lock(&sc->lock);
sc->ops = FF_SO_KEVENT;
sc->args = args;

View File

@ -9,9 +9,6 @@
#define SOCKET_OPS_ZONE_NAME "ff_socket_ops_zone_%d"
/* Must be power of 2 */
#define SOCKET_OPS_CONTEXT_MAX_NUM (2 << 5)
#define SOCKET_OPS_CONTEXT_NAME_SIZE 32
#define SOCKET_OPS_CONTEXT_NAME "ff_so_context_"
@ -43,6 +40,10 @@ ff_set_max_so_context(uint16_t count)
return -1;
}
if (count > SOCKET_OPS_CONTEXT_MAX_NUM) {
count = SOCKET_OPS_CONTEXT_MAX_NUM;
}
ff_max_so_context = count;
return 0;
@ -82,6 +83,7 @@ ff_create_so_memzone()
so_zone_tmp->mask = so_zone_tmp->count - 1;
so_zone_tmp->free = so_zone_tmp->count;
so_zone_tmp->idx = 0;
memset(so_zone_tmp->inuse, 0, SOCKET_OPS_CONTEXT_MAX_NUM);
so_zone_tmp->sc = (struct ff_so_context *)(so_zone_tmp + 1);
for (i = 0; i < ff_max_so_context; i++) {
@ -89,7 +91,7 @@ ff_create_so_memzone()
rte_spinlock_init(&sc->lock);
sc->status = FF_SC_IDLE;
sc->idx = i;
sc->inuse = 0;
//so_zone_tmp->inuse[i] = 0;
if (sem_init(&sc->wait_sem, 1, 0) == -1) {
ERR_LOG("Initialize semaphore failed:%d\n", errno);
@ -155,8 +157,8 @@ ff_attach_so_context(int proc_id)
for (i = 0; i < ff_so_zone->count; i++) {
uint16_t idx = (ff_so_zone->idx + i) & ff_so_zone->mask;
sc = &ff_so_zone->sc[idx];
if (sc->inuse == 0) {
sc->inuse = 1;
if (ff_so_zone->inuse[idx] == 0) {
ff_so_zone->inuse[idx] = 1;
rte_spinlock_init(&sc->lock);
sc->status = FF_SC_IDLE;
ff_so_zone->free--;
@ -190,19 +192,19 @@ ff_detach_so_context(struct ff_so_context *sc)
}
ERR_LOG("detach sc:%p, ops:%d, status:%d, idx:%d, inuse:%d, so free:%u, idx:%u\n",
sc, sc->ops, sc->status, sc->idx, sc->inuse, ff_so_zone->free, ff_so_zone->idx);
sc, sc->ops, sc->status, sc->idx, ff_so_zone->inuse[sc->idx], ff_so_zone->free, ff_so_zone->idx);
rte_spinlock_lock(&ff_so_zone->lock);
if (sc->inuse == 1) {
sc->inuse = 0;
if (ff_so_zone->inuse[sc->idx] == 1) {
ff_so_zone->inuse[sc->idx] = 0;
ff_so_zone->free++;
ff_so_zone->idx = sc->idx;
}
ERR_LOG("detach sc:%p, ops:%d, status:%d, idx:%d, inuse:%d, so free:%u, idx:%u\n",
sc, sc->ops, sc->status, sc->idx, sc->inuse, ff_so_zone->free, ff_so_zone->idx);
sc, sc->ops, sc->status, sc->idx, ff_so_zone->inuse[sc->idx], ff_so_zone->free, ff_so_zone->idx);
rte_spinlock_unlock(&ff_so_zone->lock);
}

View File

@ -450,6 +450,8 @@ ff_handle_socket_ops(struct ff_so_context *sc)
sc->error = errno;
if (sc->ops == FF_SO_EPOLL_WAIT || sc->ops == FF_SO_KEVENT) {
DEBUG_LOG("ff_event_loop_nb:%d/%d, ff_next_event_flag:%d\n",
ff_event_loop_nb, ff_next_event_flag);
if (ff_event_loop_nb > 0) {
ff_next_event_flag = 1;
} else {
@ -478,22 +480,33 @@ ff_handle_socket_ops(struct ff_so_context *sc)
void
ff_handle_each_context()
{
uint16_t i, nb_handled;
uint16_t i, nb_handled, tmp;
ff_event_loop_nb = 0;
rte_spinlock_lock(&ff_so_zone->lock);
assert(ff_so_zone->count >= ff_so_zone->free);
tmp = nb_handled = ff_so_zone->count - ff_so_zone->free;
while(1) {
rte_spinlock_lock(&ff_so_zone->lock);
assert(ff_so_zone->count >= ff_so_zone->free);
nb_handled = ff_so_zone->count - ff_so_zone->free;
nb_handled = tmp;
if (nb_handled) {
for (i = 0; i < ff_so_zone->count; i++) {
struct ff_so_context *sc = &ff_so_zone->sc[i];
if (sc->inuse == 0) {
DEBUG_LOG("so:%p, so->count:%d,%p, sc:%p, sc->inuse:%d,%p, i:%d, nb:%d, all_nb:%d\n",
ff_so_zone, ff_so_zone->count, &ff_so_zone->count,
sc, ff_so_zone->inuse[i], &ff_so_zone->inuse[i], i, nb_handled, tmp);
if (ff_so_zone->inuse[i] == 0) {
continue;
}
ff_handle_socket_ops(sc);
/* Dirty read first, and then try to lock sc and real read. */
if (sc->status == FF_SC_REQ) {
ff_handle_socket_ops(sc);
}
nb_handled--;
if (!nb_handled) {
@ -502,13 +515,13 @@ ff_handle_each_context()
}
}
rte_spinlock_unlock(&ff_so_zone->lock);
if (--ff_event_loop_nb <= 0 || ff_next_event_flag == 1) {
break;
}
rte_pause();
}
rte_spinlock_unlock(&ff_so_zone->lock);
}

View File

@ -28,6 +28,9 @@
#define DEBUG_LOG ERR_LOG
#endif
/* Must be power of 2 */
#define SOCKET_OPS_CONTEXT_MAX_NUM (1 << 5)
enum FF_SOCKET_OPS {
FF_SO_SOCKET,
FF_SO_LISTEN,
@ -71,36 +74,38 @@ struct ff_socket_ops_zone {
rte_spinlock_t lock;
/* total number of so_contex, must be power of 2 */
uint16_t count;
uint16_t mask;
uint8_t count;
uint8_t mask;
/* free number of so_context */
uint16_t free;
uint8_t free;
uint16_t idx;
uint8_t idx;
/* 1 if used, else 0, most access */
uint8_t inuse[SOCKET_OPS_CONTEXT_MAX_NUM];
struct ff_so_context *sc;
} __attribute__((packed));
uint8_t padding[16];
} __attribute__((aligned(RTE_CACHE_LINE_SIZE)));
struct ff_so_context {
rte_spinlock_t lock;
sem_t wait_sem;
enum FF_SOCKET_OPS ops;
enum FF_SO_CONTEXT_STATUS status;
void *args;
enum FF_SOCKET_OPS ops;
int status;
int idx;
rte_spinlock_t lock;
/* result of ops processing */
ssize_t result;
/* errno if failed */
int error;
/* result of ops processing */
int result;
int idx;
/* 1 if used, else 0 */
int inuse;
sem_t wait_sem; /* 32 bytes */
// listen fd, refcount..
} __attribute__((packed));
} __attribute__((aligned(RTE_CACHE_LINE_SIZE)));
extern __FF_THREAD struct ff_socket_ops_zone *ff_so_zone;