qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-devel] [PATCH] net: reduce the unnecessary memory allocation o


From: Jason Wang
Subject: Re: [Qemu-devel] [PATCH] net: reduce the unnecessary memory allocation of multiqueue
Date: Fri, 22 Feb 2013 14:08:20 +0800
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/20130106 Thunderbird/17.0.2

On 02/22/2013 06:32 AM, Anthony Liguori wrote:
> Jason Wang <address@hidden> writes:
>
>> Edivaldo reports a problem that the array of NetClientState in NICState is 
>> too
>> large - MAX_QUEUE_NUM(1024) which will wastes memory even if multiqueue is 
>> not
>> used.
>>
>> Instead of static arrays, solving this issue by allocating the queues on 
>> demand
>> for both the NetClientState array in NICState and VirtIONetQueue array in
>> VirtIONet.
>>
>> Tested by myself, with single virtio-net-pci device. The memory allocation is
>> almost the same as when multiqueue is not merged.
>>
>> Cc: Edivaldo de Araujo Pereira <address@hidden>
>> Cc: address@hidden
>> Signed-off-by: Jason Wang <address@hidden>
>> ---
>>  hw/virtio-net.c   |    6 ++++--
>>  include/net/net.h |    2 +-
>>  net/net.c         |   19 +++++++++----------
>>  3 files changed, 14 insertions(+), 13 deletions(-)
>>
>> diff --git a/hw/virtio-net.c b/hw/virtio-net.c
>> index 573c669..70ab641 100644
>> --- a/hw/virtio-net.c
>> +++ b/hw/virtio-net.c
>> @@ -44,7 +44,7 @@ typedef struct VirtIONet
>>      VirtIODevice vdev;
>>      uint8_t mac[ETH_ALEN];
>>      uint16_t status;
>> -    VirtIONetQueue vqs[MAX_QUEUE_NUM];
>> +    VirtIONetQueue *vqs;
>>      VirtQueue *ctrl_vq;
>>      NICState *nic;
>>      uint32_t tx_timeout;
>> @@ -1326,8 +1326,9 @@ VirtIODevice *virtio_net_init(DeviceState *dev, 
>> NICConf *conf,
>>      n->vdev.set_status = virtio_net_set_status;
>>      n->vdev.guest_notifier_mask = virtio_net_guest_notifier_mask;
>>      n->vdev.guest_notifier_pending = virtio_net_guest_notifier_pending;
>> +    n->max_queues = MAX(conf->queues, 1);
> I think you mean MIN here.

Then the at most 1 queue will be created. MAX is used to create at least
one queue when conf->queues is zero which means the nic were not created
with netdev.
>> +    n->vqs = g_malloc0(sizeof(VirtIONetQueue) * n->max_queues);
>>      n->vqs[0].rx_vq = virtio_add_queue(&n->vdev, 256, virtio_net_handle_rx);
>> -    n->max_queues = conf->queues;
>>      n->curr_queues = 1;
>>      n->vqs[0].n = n;
>>      n->tx_timeout = net->txtimer;
>> @@ -1397,6 +1398,7 @@ void virtio_net_exit(VirtIODevice *vdev)
>>  
>>      g_free(n->mac_table.macs);
>>      g_free(n->vlans);
>> +    g_free(n->vqs);
>>  
>>      for (i = 0; i < n->max_queues; i++) {
>>          VirtIONetQueue *q = &n->vqs[i];
>> diff --git a/include/net/net.h b/include/net/net.h
>> index 43a045e..cb049a1 100644
>> --- a/include/net/net.h
>> +++ b/include/net/net.h
>> @@ -72,7 +72,7 @@ struct NetClientState {
>>  };
>>  
>>  typedef struct NICState {
>> -    NetClientState ncs[MAX_QUEUE_NUM];
>> +    NetClientState *ncs;
>>      NICConf *conf;
>>      void *opaque;
>>      bool peer_deleted;
>> diff --git a/net/net.c b/net/net.c
>> index be03a8d..6262ed0 100644
>> --- a/net/net.c
>> +++ b/net/net.c
>> @@ -235,23 +235,20 @@ NICState *qemu_new_nic(NetClientInfo *info,
>>                         const char *name,
>>                         void *opaque)
>>  {
>> -    NetClientState *nc;
>>      NetClientState **peers = conf->peers.ncs;
>>      NICState *nic;
>> -    int i;
>> +    int i, queues = MAX(1, conf->queues);
> And here.  This patch is what had created problems for me.

Same as above, so I think the code is ok or anything I miss?
>
> Regards,
>
> Anthony Liguori
>
>>  
>>      assert(info->type == NET_CLIENT_OPTIONS_KIND_NIC);
>>      assert(info->size >= sizeof(NICState));
>>  
>> -    nc = qemu_new_net_client(info, peers[0], model, name);
>> -    nc->queue_index = 0;
>> -
>> -    nic = qemu_get_nic(nc);
>> +    nic = g_malloc0(info->size + sizeof(NetClientState) * queues);
>> +    nic->ncs = (void *)nic + info->size;
>>      nic->conf = conf;
>>      nic->opaque = opaque;
>>  
>> -    for (i = 1; i < conf->queues; i++) {
>> -        qemu_net_client_setup(&nic->ncs[i], info, peers[i], model, nc->name,
>> +    for (i = 0; i < queues; i++) {
>> +        qemu_net_client_setup(&nic->ncs[i], info, peers[i], model, name,
>>                                NULL);
>>          nic->ncs[i].queue_index = i;
>>      }
>> @@ -261,7 +258,7 @@ NICState *qemu_new_nic(NetClientInfo *info,
>>  
>>  NetClientState *qemu_get_subqueue(NICState *nic, int queue_index)
>>  {
>> -    return &nic->ncs[queue_index];
>> +    return nic->ncs + queue_index;
>>  }
>>  
>>  NetClientState *qemu_get_queue(NICState *nic)
>> @@ -273,7 +270,7 @@ NICState *qemu_get_nic(NetClientState *nc)
>>  {
>>      NetClientState *nc0 = nc - nc->queue_index;
>>  
>> -    return DO_UPCAST(NICState, ncs[0], nc0);
>> +    return (NICState *)((void *)nc0 - nc->info->size);
>>  }
>>  
>>  void *qemu_get_nic_opaque(NetClientState *nc)
>> @@ -368,6 +365,8 @@ void qemu_del_nic(NICState *nic)
>>          qemu_cleanup_net_client(nc);
>>          qemu_free_net_client(nc);
>>      }
>> +
>> +    g_free(nic);
>>  }
>>  
>>  void qemu_foreach_nic(qemu_nic_foreach func, void *opaque)
>> -- 
>> 1.7.1
>




reply via email to

[Prev in Thread] Current Thread [Next in Thread]