tstVBoxAPIPerf.cpp revision 50546d921ccc80de6aaa216e7c3831834c7d0e47
/* $Id$ */
/** @file
* tstVBoxAPIPerf - Checks the performance of the COM / XPOM API.
*/
/*
* Copyright (C) 2006-2013 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* you can redistribute it and/or modify it under the terms of the GNU
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
/*******************************************************************************
* Header Files *
*******************************************************************************/
#include <VBox/com/com.h>
#include <VBox/com/string.h>
#include <VBox/com/array.h>
#include <VBox/com/Guid.h>
#include <VBox/com/ErrorInfo.h>
#include <VBox/com/VirtualBox.h>
#include <VBox/sup.h>
#include <iprt/test.h>
#include <iprt/time.h>
/*******************************************************************************
* Global Variables *
*******************************************************************************/
static RTTEST g_hTest;
/** Worker fro TST_COM_EXPR(). */
static HRESULT tstComExpr(HRESULT hrc, const char *pszOperation, int iLine)
{
if (FAILED(hrc))
RTTestFailed(g_hTest, "%s failed on line %u with hrc=%Rhrc", pszOperation, iLine, hrc);
return hrc;
}
/** Macro that executes the given expression and report any failure.
* The expression must return a HRESULT. */
#define TST_COM_EXPR(expr) tstComExpr(expr, #expr, __LINE__)
static void tstApiPrf1(IVirtualBox *pVBox)
{
RTTestSub(g_hTest, "IVirtualBox::Revision performance");
uint32_t const cCalls = 65536;
uint32_t cLeft = cCalls;
uint64_t uStartTS = RTTimeNanoTS();
while (cLeft-- > 0)
{
ULONG uRev;
HRESULT hrc = pVBox->COMGETTER(Revision)(&uRev);
if (FAILED(hrc))
{
tstComExpr(hrc, "IVirtualBox::Revision", __LINE__);
return;
}
}
uint64_t uElapsed = RTTimeNanoTS() - uStartTS;
RTTestValue(g_hTest, "IVirtualBox::Revision average", uElapsed / cCalls, RTTESTUNIT_NS_PER_CALL);
RTTestSubDone(g_hTest);
}
static void tstApiPrf2(IVirtualBox *pVBox)
{
RTTestSub(g_hTest, "IVirtualBox::Version performance");
uint32_t const cCalls = 65536;
uint32_t cLeft = cCalls;
uint64_t uStartTS = RTTimeNanoTS();
while (cLeft-- > 0)
{
com::Bstr bstrVersion;
HRESULT hrc = pVBox->COMGETTER(Version)(bstrVersion.asOutParam());
if (FAILED(hrc))
{
tstComExpr(hrc, "IVirtualBox::Version", __LINE__);
return;
}
}
uint64_t uElapsed = RTTimeNanoTS() - uStartTS;
RTTestValue(g_hTest, "IVirtualBox::Version average", uElapsed / cCalls, RTTESTUNIT_NS_PER_CALL);
RTTestSubDone(g_hTest);
}
static void tstApiPrf3(IVirtualBox *pVBox)
{
RTTestSub(g_hTest, "IVirtualBox::Host performance");
/* The first call. */
uint64_t uStartTS = RTTimeNanoTS();
IHost *pHost = NULL;
HRESULT hrc = pVBox->COMGETTER(Host)(&pHost);
if (FAILED(hrc))
{
tstComExpr(hrc, "IVirtualBox::Host", __LINE__);
return;
}
pHost->Release();
uint64_t uElapsed = RTTimeNanoTS() - uStartTS;
RTTestValue(g_hTest, "IVirtualBox::Host first", uElapsed, RTTESTUNIT_NS);
/* Subsequent calls. */
uint32_t const cCalls1 = 4096;
uint32_t cLeft = cCalls1;
uStartTS = RTTimeNanoTS();
while (cLeft-- > 0)
{
IHost *pHost2 = NULL;
hrc = pVBox->COMGETTER(Host)(&pHost2);
if (FAILED(hrc))
{
tstComExpr(hrc, "IVirtualBox::Host", __LINE__);
return;
}
pHost2->Release();
}
uElapsed = RTTimeNanoTS() - uStartTS;
RTTestValue(g_hTest, "IVirtualBox::Host average", uElapsed / cCalls1, RTTESTUNIT_NS_PER_CALL);
/* Keep a reference around and see how that changes things.
Note! VBoxSVC is not creating and destroying Host(). */
pHost = NULL;
hrc = pVBox->COMGETTER(Host)(&pHost);
uint32_t const cCalls2 = 16384;
cLeft = cCalls2;
uStartTS = RTTimeNanoTS();
while (cLeft-- > 0)
{
IHost *pHost2 = NULL;
hrc = pVBox->COMGETTER(Host)(&pHost2);
if (FAILED(hrc))
{
tstComExpr(hrc, "IVirtualBox::Host", __LINE__);
pHost->Release();
return;
}
pHost2->Release();
}
uElapsed = RTTimeNanoTS() - uStartTS;
RTTestValue(g_hTest, "IVirtualBox::Host 2nd ref", uElapsed / cCalls2, RTTESTUNIT_NS_PER_CALL);
pHost->Release();
RTTestSubDone(g_hTest);
}
int main(int argc, char **argv)
{
/*
* Initialization.
*/
RTEXITCODE rcExit = RTTestInitAndCreate("tstVBoxAPIPerf", &g_hTest);
if (rcExit != RTEXITCODE_SUCCESS)
return rcExit;
SUPR3Init(NULL); /* Better time support. */
RTTestBanner(g_hTest);
RTTestSub(g_hTest, "Initializing COM and singletons");
HRESULT hrc = com::Initialize();
if (SUCCEEDED(hrc))
{
ComPtr<IVirtualBox> ptrVBox;
hrc = TST_COM_EXPR(ptrVBox.createLocalObject(CLSID_VirtualBox));
if (SUCCEEDED(hrc))
{
ComPtr<ISession> ptrSession;
hrc = TST_COM_EXPR(ptrSession.createInprocObject(CLSID_Session));
if (SUCCEEDED(hrc))
{
RTTestSubDone(g_hTest);
/*
* Call test functions.
*/
tstApiPrf1(ptrVBox);
tstApiPrf2(ptrVBox);
tstApiPrf3(ptrVBox);
/** @todo Find something that returns a 2nd instance of an interface and see
* how if wrapper stuff is reused in any way. */
}
}
ptrVBox.setNull();
com::Shutdown();
}
else
RTTestIFailed("com::Initialize failed with hrc=%Rhrc", hrc);
return RTTestSummaryAndDestroy(g_hTest);
}