[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