[sheepdog] [PATCH v2] sockfd cache: grow fds count dynamically
MORITA Kazutaka
morita.kazutaka at lab.ntt.co.jp
Mon Jul 23 12:18:31 CEST 2012
At Mon, 23 Jul 2012 17:41:27 +0800,
Liu Yuan wrote:
>
> From: Liu Yuan <tailai.ly at taobao.com>
>
> v2:
> - fix memory leak in check_idx()
> - remove extra whitespace
> ---------------------------------- >8
>
> This will scale sheep daemon to serve more VMs on one node and do
> it adoptively and automatically.
>
> - fd count default to 16 instead of previous 8
>
> Signed-off-by: Liu Yuan <tailai.ly at taobao.com>
> ---
> sheep/sheep.c | 1 +
> sheep/sheep_priv.h | 1 +
> sheep/sockfd_cache.c | 127 ++++++++++++++++++++++++++++++++++++++------------
> 3 files changed, 98 insertions(+), 31 deletions(-)
>
> diff --git a/sheep/sheep.c b/sheep/sheep.c
> index df28a94..380a129 100644
> --- a/sheep/sheep.c
> +++ b/sheep/sheep.c
> @@ -344,6 +344,7 @@ int main(int argc, char **argv)
> sys->recovery_wqueue = init_work_queue("recovery", true);
> sys->deletion_wqueue = init_work_queue("deletion", true);
> sys->block_wqueue = init_work_queue("block", true);
> + sys->sockfd_wqueue = init_work_queue("sockfd", true);
> if (!sys->gateway_wqueue || !sys->io_wqueue ||!sys->recovery_wqueue ||
> !sys->deletion_wqueue || !sys->block_wqueue)
> exit(1);
> diff --git a/sheep/sheep_priv.h b/sheep/sheep_priv.h
> index e455d27..530fe14 100644
> --- a/sheep/sheep_priv.h
> +++ b/sheep/sheep_priv.h
> @@ -122,6 +122,7 @@ struct cluster_info {
> struct work_queue *deletion_wqueue;
> struct work_queue *recovery_wqueue;
> struct work_queue *block_wqueue;
> + struct work_queue *sockfd_wqueue;
> };
>
> struct siocb {
> diff --git a/sheep/sockfd_cache.c b/sheep/sockfd_cache.c
> index aa90299..c130ea6 100644
> --- a/sheep/sockfd_cache.c
> +++ b/sheep/sockfd_cache.c
> @@ -48,23 +48,33 @@ static struct sockfd_cache sockfd_cache = {
> .lock = PTHREAD_RWLOCK_INITIALIZER,
> };
>
> +/*
> + * Suppose request size from Guest is 512k, then 4M / 512k = 8, so at
> + * most 8 requests can be issued to the same sheep object. Based on this
> + * assumption, '16' would be effecient for servers that only host 2~4
> + * Guests.
> + *
> + * This fd count will be dynamically grown when the idx reaches watermark.
> + */
> +#define DEFAULT_FDS_COUNT 16
> +#define DEFAULT_FDS_WATERMARK 12
Should comment that the value is (16 * 3 / 4)?
> +
> +/* How many FDs we cache for one node */
> +static int fds_count = DEFAULT_FDS_COUNT;
> +
> +struct sockfd_cache_fd {
> + int fd;
> + uint8_t fd_in_use;
Simply, how about 'in_use'?
> +};
> +
> struct sockfd_cache_entry {
> struct rb_node rb;
> struct node_id nid;
> -#define SOCKFD_CACHE_MAX_FD 8 /* How many FDs we cache for one node */
> - /*
> - * FIXME: Make this macro configurable.
> - *
> - * Suppose request size from Guest is 512k, then 4M / 512k = 8, so at
> - * most 8 requests can be issued to the same sheep object. Based on this
> - * assumption, '8' would be effecient for servers that only host 4~8
> - * Guests, but for powerful servers that can host dozens of Guests, we
> - * might consider bigger value.
> - */
> - int fd[SOCKFD_CACHE_MAX_FD];
> - uint8_t fd_in_use[SOCKFD_CACHE_MAX_FD];
> + struct sockfd_cache_fd *fds;
> };
>
> +#define fds_bytes (sizeof(struct sockfd_cache_fd) * fds_count)
> +
> static struct sockfd_cache_entry *
> sockfd_cache_insert(struct sockfd_cache_entry *new)
> {
> @@ -118,8 +128,8 @@ static inline int get_free_slot(struct sockfd_cache_entry *entry)
> {
> int idx = -1, i;
>
> - for (i = 0; i < SOCKFD_CACHE_MAX_FD; i++) {
> - if (uatomic_cmpxchg(&entry->fd_in_use[i], 0, 1))
> + for (i = 0; i < fds_count; i++) {
> + if (uatomic_cmpxchg(&entry->fds[i].fd_in_use, 0, 1))
> continue;
> idx = i;
> break;
> @@ -155,8 +165,8 @@ out:
> static inline bool slots_all_free(struct sockfd_cache_entry *entry)
> {
> int i;
> - for (i = 0; i < SOCKFD_CACHE_MAX_FD; i++)
> - if (uatomic_read(&entry->fd_in_use[i]))
> + for (i = 0; i < fds_count; i++)
> + if (uatomic_read(&entry->fds[i].fd_in_use))
> return false;
> return true;
> }
> @@ -164,9 +174,9 @@ static inline bool slots_all_free(struct sockfd_cache_entry *entry)
> static inline void destroy_all_slots(struct sockfd_cache_entry *entry)
> {
> int i;
> - for (i = 0; i < SOCKFD_CACHE_MAX_FD; i++)
> - if (entry->fd[i] != -1)
> - close(entry->fd[i]);
> + for (i = 0; i < fds_count; i++)
> + if (entry->fds[i].fd != -1)
> + close(entry->fds[i].fd);
> }
>
> /*
> @@ -220,11 +230,12 @@ void sockfd_cache_del(struct node_id *nid)
>
> static void sockfd_cache_add_nolock(struct node_id *nid)
> {
> - struct sockfd_cache_entry *new = xzalloc(sizeof(*new));
> + struct sockfd_cache_entry *new = xmalloc(sizeof(*new));
> int i;
>
> - for (i = 0; i < SOCKFD_CACHE_MAX_FD; i++)
> - new->fd[i] = -1;
> + new->fds = xzalloc(fds_bytes);
Isn't it easier to understand to write directly
new->fds = xzalloc(sizeof(struct sockfd_cache_fd) * fds_count)
than using a macro?
The other parts look good to me.
Thanks,
Kazutaka
More information about the sheepdog
mailing list