[libvirt] [PATCH v1 00/31] Drop network driver lock

Kashyap Chamarthy kchamart at redhat.com
Fri Feb 27 13:59:49 UTC 2015


On Fri, Feb 27, 2015 at 02:37:00PM +0100, Michal Privoznik wrote:
> On 26.02.2015 15:17, Michal Privoznik wrote:
> > <snip/>
> > 
> 
> BTW: I've done some testing locally and it helped me to find a bug in my
> patches (I've just proposed the diff to be squashed in). Basically, my
> test program defines 10 dummy networks, and spawns a thread over each
> one of them. The thread does 1000 iterations of some network API calls,
> e.g. define, undefine, start, destroy, IsActive, IsPersistent, and so
> on. And the results are astonishing:
> 
> Without my patches:
> 
> $ time ./test_network_lock qemu+tcp://localhost/system
> Connected. Starting workers ...
> Waiting for workers to end ...
> 
> real    0m54.083s
> user    0m1.317s
> sys     0m1.302s
> 
> 
> With my patches:
> 
> $ time ./test_network_lock qemu+tcp://localhost/system
> Connected. Starting workers ...
> Waiting for workers to end ...
> 
> real    0m42.355s
> user    0m1.231s
> sys     0m1.324s
> 
> So nearly 12 seconds speed up! The test program can be found at [1].
> 
> Michal
> 
> 1: http://fpaste.org/191340/

Since paste bin's expire, adding the test program content below:

--------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <libvirt/libvirt.h>
#include <libvirt/virterror.h>

#define NETS 10
#define ITER 1000

static void *
workerfunc(void *opaque)
{
    virNetworkPtr *netptr = opaque;
    virNetworkPtr net = *netptr;
    virConnectPtr conn = virNetworkGetConnect(net);
    size_t i;
    char *xml = NULL;
    char *bridgename = NULL;

    for (i = 0; i < ITER; i++) {
        int isActive = virNetworkIsActive(net);
        int isPersistent = virNetworkIsPersistent(net);
        int autostart;

        if (virNetworkGetAutostart(net, &autostart) < 0) {
            fprintf(stderr, "Unable to get autostart\n");
            goto cleanup;
        }

        if (!(xml = virNetworkGetXMLDesc(net, 0))) {
            fprintf(stderr, "Unable to get net XML\n");
            goto cleanup;
        }

        if (!(bridgename = virNetworkGetBridgeName(net))) {
            fprintf(stderr, "Unable to get net bridge name\n");
            goto cleanup;
        }

        if (virNetworkCreate(net) < 0) {
            fprintf(stderr, "Unable to start network\n");
            goto cleanup;
        }

        if (virNetworkDestroy(net) < 0) {
            fprintf(stderr, "Unable to destroy network\n");
            goto cleanup;
        }

        if (virNetworkUndefine(net) < 0) {
            fprintf(stderr, "Unable to undefine network\n");
            goto cleanup;
        }

        if (!(net = virNetworkDefineXML(conn, xml))) {
            fprintf(stderr, "Unable to define network back\n");
            goto cleanup;
        }

        free(xml);
        free(bridgename);
        xml = bridgename = NULL;
    }

 cleanup:
    free(xml);
    free(bridgename);
    *netptr = net;
    return NULL;
}

static int
defineNets(virConnectPtr conn,
           virNetworkPtr **nets,
           int *nnets)
{
    int ret = -1;
    char *defxml = NULL;
    const char *xml = \
"<network>" \
"  <name>testnet%d</name>" \
"  <forward mode='bridge'/>" \
"  <bridge name='br%d'/>" \
"</network>";

    for (*nnets = 0; *nnets < NETS; (*nnets)++) {
        virNetworkPtr net;

        if (asprintf(&defxml, xml, *nnets, *nnets) < 0) {
            fprintf(stderr, "Unable to create network XML\n");
            goto cleanup;
        }

        if (!(*nets = realloc(*nets, (*nnets + 1) * sizeof((*nets)[0])))) {
            fprintf(stderr, "Unable to allocate memory\n");
            goto cleanup;
        }

        if (!(net = virNetworkDefineXML(conn, defxml))) {
            fprintf(stderr, "Unable to define network\n");
            goto cleanup;
        }
        (*nets)[*nnets] = net;
    }

    ret = 0;
 cleanup:
    free(defxml);
    if (ret < 0) {
        while (*nnets) {
            (*nnets)--;
            virNetworkUndefine((*nets)[*nnets]);
            virNetworkFree((*nets)[*nnets]);
        }
    }
    return ret;
}

int main(int argc, char **argv)
{
    int ret = -1;
    virConnectPtr conn = NULL;
    virNetworkPtr *nets = NULL;
    int nnets = 0;
    pthread_t workers[NETS];
    size_t nworkers = 0;

    if (virInitialize() < 0) {
        fprintf(stderr, "Failed to initialize libvirt.\n");
        return -1;
    }

    conn = virConnectOpenAuth(argc > 1 ? argv[1] : NULL,
                              virConnectAuthPtrDefault, 0);
    if (!conn) {
        fprintf(stderr, "error opening\n");
        return -1;
    }

    if (defineNets(conn, &nets, &nnets) < 0)
        goto cleanup;

    printf("Connected. Starting workers ...\n");
    for (nworkers = 0; nworkers < nnets; nworkers++) {
        if (pthread_create(&workers[nworkers], NULL, workerfunc, &nets[nworkers]) < 0)
            goto cleanup;
    }

    printf("Waiting for workers to end ...\n");
    while (nworkers)
        pthread_join(workers[--nworkers], NULL);

    ret = 0;
 cleanup:
    while (nnets) {
        nnets--;
        virNetworkDestroy(nets[nnets]);
        virNetworkUndefine(nets[nnets]);
        virNetworkFree(nets[nnets]);
    }
    free(nets);
    while (nworkers)
        pthread_join(workers[--nworkers], NULL);
    virConnectClose(conn);
    return ret;
}
--------------------------------------------------------------------

-- 
/kashyap




More information about the libvir-list mailing list