Version 6.1.4.1, tag libreoffice-6.1.4.1
[LibreOffice.git] / testtools / source / performance / ubtest.cxx
blob89643574198eca33abd542f5b1b937ad0204e0a4
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
21 #include <stdio.h>
22 #include <math.h>
23 #include <string>
24 #include <map>
25 #include <unordered_map>
27 #include <osl/diagnose.h>
28 #include <osl/mutex.hxx>
29 #include <osl/module.h>
30 #include <osl/process.h>
31 #include <osl/thread.h>
32 #include <osl/conditn.hxx>
33 #include <osl/time.h>
35 #ifdef _WIN32
36 #if !defined WIN32_LEAN_AND_MEAN
37 # define WIN32_LEAN_AND_MEAN
38 #endif
39 #include <windows.h>
40 #else
41 #include <sys/times.h>
42 #include <unistd.h>
43 #endif
45 #include <rtl/string.hxx>
46 #include <rtl/strbuf.hxx>
47 #include <rtl/ustrbuf.hxx>
49 #include <uno/environment.hxx>
50 #include <uno/lbnames.h>
51 #include <uno/mapping.hxx>
53 #include <cppuhelper/factory.hxx>
54 #include <cppuhelper/implbase.hxx>
56 #include <com/sun/star/lang/XServiceInfo.hpp>
57 #include <com/sun/star/lang/XComponent.hpp>
58 #include <com/sun/star/lang/XMain.hpp>
59 #include <com/sun/star/lang/XInitialization.hpp>
60 #include <com/sun/star/loader/XImplementationLoader.hpp>
61 #include <com/sun/star/registry/XRegistryKey.hpp>
62 #include <com/sun/star/bridge/XUnoUrlResolver.hpp>
63 #include <com/sun/star/container/XSet.hpp>
64 #include <com/sun/star/test/performance/XPerformanceTest.hpp>
66 #define NLOOP 200000000
68 using namespace osl;
69 using namespace cppu;
70 using namespace com::sun::star::uno;
71 using namespace com::sun::star::lang;
72 using namespace com::sun::star::loader;
73 using namespace com::sun::star::registry;
74 using namespace com::sun::star::bridge;
75 using namespace com::sun::star::container;
76 using namespace com::sun::star::test::performance;
79 #define SERVICENAME "com.sun.star.test.performance.PerformanceTest"
80 #define IMPLNAME "com.sun.star.comp.performance.PerformanceTest"
82 namespace benchmark_test
85 static inline sal_uInt32 getSystemTicks()
87 #ifdef _WIN32
88 return (sal_uInt32)GetTickCount();
89 #else // only UNX supported for now
90 static sal_uInt32 nImplTicksPerSecond = 0;
91 static double dImplTicksPerSecond;
92 static double dImplTicksULONGMAX;
94 struct tms aTms;
95 sal_uInt32 nTicks = (sal_uInt32)times( &aTms );
97 if ( !nImplTicksPerSecond )
99 nImplTicksPerSecond = sysconf(_SC_CLK_TCK);
100 dImplTicksPerSecond = nImplTicksPerSecond;
101 dImplTicksULONGMAX = (double)(sal_uInt32)ULONG_MAX;
104 double fTicks = nTicks;
105 fTicks *= 1000;
106 fTicks /= dImplTicksPerSecond;
107 fTicks = fmod (fTicks, dImplTicksULONGMAX);
109 return (sal_uInt32)fTicks;
110 #endif
114 static void out( const sal_Char * pText, FILE * stream = stderr,
115 sal_Int32 nStart = -1, sal_Char cFillchar = ' ' )
117 static sal_Int32 s_nPos = 0;
119 sal_Char ar[2] = { cFillchar, 0 };
120 while (s_nPos < nStart)
122 ::fprintf( stream, ar );
123 ++s_nPos;
126 ::fprintf( stream, pText );
128 for ( const sal_Char * p = pText; *p; ++p )
130 if (*p == '\n')
131 s_nPos = 0;
132 else
133 ++s_nPos;
137 static inline void out( const OUString & rText, FILE * stream = stderr,
138 sal_Int32 nStart = -1, sal_Char cFillchar = ' ' )
140 OString aText( OUStringToOString( rText, RTL_TEXTENCODING_ASCII_US ) );
141 out( aText.getStr(), stream, nStart, cFillchar );
144 static inline void out( double fVal, FILE * stream = stderr,
145 sal_Int32 nStart = -1, sal_Char cFillchar = ' ' )
147 sal_Char ar[128];
148 ::snprintf( ar, sizeof(ar), (fVal < 0.000001 ? "%g" : "%f"), fVal );
149 out( ar, stream, nStart, cFillchar );
152 static inline void out( sal_Int64 nVal, FILE * stream = stderr,
153 sal_Int32 nStart = -1, sal_Char cFillchar = ' ' )
155 sal_Char ar[128];
156 ::snprintf( ar, sizeof(ar), "%ld", nVal );
157 out( ar, stream, nStart, cFillchar );
161 Reference< XSingleServiceFactory > loadLibComponentFactory(
162 const OUString & rLibName, const OUString & rImplName,
163 const Reference< XMultiServiceFactory > & xSF, const Reference< XRegistryKey > & xKey )
165 Reference< XSingleServiceFactory > xRet;
167 OUStringBuffer aLibNameBuf( 32 );
168 #ifdef SAL_UNX
169 aLibNameBuf.append( "lib" );
170 aLibNameBuf.append( rLibName );
171 aLibNameBuf.append( ".so" );
172 #else
173 aLibNameBuf.append( rLibName );
174 aLibNameBuf.append( ".dll" );
175 #endif
176 OUString aLibName( aLibNameBuf.makeStringAndClear() );
177 oslModule lib = osl_loadModule( aLibName.pData, SAL_LOADMODULE_LAZY | SAL_LOADMODULE_GLOBAL );
179 if (lib)
181 void * pSym;
183 // ========================= LATEST VERSION =========================
184 OUString aGetEnvName( COMPONENT_GETENV );
185 if (pSym = osl_getSymbol( lib, aGetEnvName.pData ))
187 uno_Environment * pCurrentEnv = 0;
188 uno_Environment * pEnv = 0;
189 const sal_Char * pEnvTypeName = 0;
190 (*((component_getImplementationEnvironmentFunc)pSym))( &pEnvTypeName, &pEnv );
192 sal_Bool bNeedsMapping =
193 (pEnv || 0 != rtl_str_compare( pEnvTypeName, CPPU_CURRENT_LANGUAGE_BINDING_NAME ));
195 OUString aEnvTypeName( OUString::createFromAscii( pEnvTypeName ) );
197 if (bNeedsMapping)
199 if (! pEnv)
200 uno_getEnvironment( &pEnv, aEnvTypeName.pData, 0 );
201 if (pEnv)
203 OUString aCppEnvTypeName( CPPU_CURRENT_LANGUAGE_BINDING_NAME );
204 uno_getEnvironment( &pCurrentEnv, aCppEnvTypeName.pData, 0 );
205 if (pCurrentEnv)
206 bNeedsMapping = (pEnv != pCurrentEnv);
210 OUString aGetFactoryName( COMPONENT_GETFACTORY );
211 if (pSym = osl_getSymbol( lib, aGetFactoryName.pData ))
213 OString aImplName( OUStringToOString( rImplName, RTL_TEXTENCODING_ASCII_US ) );
215 if (bNeedsMapping)
217 if (pEnv && pCurrentEnv)
219 Mapping aCurrent2Env( pCurrentEnv, pEnv );
220 Mapping aEnv2Current( pEnv, pCurrentEnv );
222 if (aCurrent2Env.is() && aEnv2Current.is())
224 void * pSMgr = aCurrent2Env.mapInterface(
225 xSF.get(), cppu::UnoType<XMultiServiceFactory>::get() );
226 void * pKey = aCurrent2Env.mapInterface(
227 xKey.get(), cppu::UnoType<XRegistryKey>::get() );
229 void * pSSF = (*((component_getFactoryFunc)pSym))(
230 aImplName.getStr(), pSMgr, pKey );
232 if (pKey)
233 (*pEnv->pExtEnv->releaseInterface)( pEnv->pExtEnv, pKey );
234 if (pSMgr)
235 (*pEnv->pExtEnv->releaseInterface)( pEnv->pExtEnv, pSMgr );
237 if (pSSF)
239 aEnv2Current.mapInterface(
240 reinterpret_cast< void ** >( &xRet ),
241 pSSF, cppu::UnoType<XSingleServiceFactory>::get() );
242 (*pEnv->pExtEnv->releaseInterface)( pEnv->pExtEnv, pSSF );
247 else
249 XSingleServiceFactory * pRet = (XSingleServiceFactory *)
250 (*((component_getFactoryFunc)pSym))(
251 aImplName.getStr(), xSF.get(), xKey.get() );
252 if (pRet)
254 xRet = pRet;
255 pRet->release();
260 if (pEnv)
261 (*pEnv->release)( pEnv );
262 if (pCurrentEnv)
263 (*pCurrentEnv->release)( pCurrentEnv );
266 // ========================= PREVIOUS VERSION =========================
267 else
269 OUString aGetFactoryName( CREATE_COMPONENT_FACTORY_FUNCTION );
270 if (pSym = osl_getSymbol( lib, aGetFactoryName.pData ))
272 OUString aCppEnvTypeName( CPPU_CURRENT_LANGUAGE_BINDING_NAME );
273 OUString aUnoEnvTypeName( UNO_LB_UNO );
274 Mapping aUno2Cpp( aUnoEnvTypeName, aCppEnvTypeName );
275 Mapping aCpp2Uno( aCppEnvTypeName, aUnoEnvTypeName );
276 OSL_ENSURE( aUno2Cpp.is() && aCpp2Uno.is(), "### cannot get uno mappings!" );
278 if (aUno2Cpp.is() && aCpp2Uno.is())
280 uno_Interface * pUComponentFactory = 0;
282 uno_Interface * pUSFactory = (uno_Interface *)aCpp2Uno.mapInterface(
283 xSF.get(), cppu::UnoType<XMultiServiceFactory>::get() );
284 uno_Interface * pUKey = (uno_Interface *)aCpp2Uno.mapInterface(
285 xKey.get(), cppu::UnoType<XRegistryKey>::get() );
287 pUComponentFactory = (*((CreateComponentFactoryFunc)pSym))(
288 rImplName.getStr(), pUSFactory, pUKey );
290 if (pUKey)
291 (*pUKey->release)( pUKey );
292 if (pUSFactory)
293 (*pUSFactory->release)( pUSFactory );
295 if (pUComponentFactory)
297 XSingleServiceFactory * pXFactory =
298 (XSingleServiceFactory *)aUno2Cpp.mapInterface(
299 pUComponentFactory, cppu::UnoType<XSingleServiceFactory>::get() );
300 (*pUComponentFactory->release)( pUComponentFactory );
302 if (pXFactory)
304 xRet = pXFactory;
305 pXFactory->release();
312 if (! xRet.is())
313 osl_unloadModule( lib );
316 return xRet;
319 template< class T >
320 static void createInstance( Reference< T > & rxOut,
321 const Reference< XMultiServiceFactory > & xMgr,
322 const OUString & rServiceName )
323 throw (RuntimeException)
325 Reference< XInterface > x( xMgr->createInstance( rServiceName ), UNO_QUERY );
327 if (! x.is())
329 static sal_Bool s_bSet = sal_False;
330 if (! s_bSet)
332 MutexGuard aGuard( Mutex::getGlobalMutex() );
333 if (! s_bSet)
335 Reference< XSet > xSet( xMgr, UNO_QUERY );
336 if (xSet.is())
338 // acceptor
339 xSet->insert( makeAny( loadLibComponentFactory(
340 OUString("acceptor"),
341 OUString("com.sun.star.comp.stoc.Acceptor"),
342 xMgr, Reference< XRegistryKey >() ) ) );
343 // connector
344 xSet->insert( makeAny( loadLibComponentFactory(
345 OUString("connectr"),
346 OUString("com.sun.star.comp.stoc.Connector"),
347 xMgr, Reference< XRegistryKey >() ) ) );
348 // iiop bridge
349 xSet->insert( makeAny( loadLibComponentFactory(
350 OUString("remotebridge"),
351 OUString("com.sun.star.bridge.Bridge.various"),
352 xMgr, Reference< XRegistryKey >() ) ) );
353 // bridge factory
354 xSet->insert( makeAny( loadLibComponentFactory(
355 OUString("brdgfctr"),
356 OUString("com.sun.star.comp.stoc.BridgeFactory"),
357 xMgr, Reference< XRegistryKey >() ) ) );
358 // uno url resolver
359 xSet->insert( makeAny( loadLibComponentFactory(
360 OUString("uuresolver"),
361 OUString("com.sun.star.comp.bridge.UnoUrlResolver"),
362 xMgr, Reference< XRegistryKey >() ) ) );
363 // java loader
364 // xSet->insert( makeAny( loadLibComponentFactory(
365 // OUString("javaloader"),
366 // OUString("com.sun.star.comp.stoc.JavaComponentLoader"),
367 // xMgr, Reference< XRegistryKey >() ) ) );
369 s_bSet = sal_True;
372 x = xMgr->createInstance( rServiceName );
375 if (! x.is())
377 throw RuntimeException( "cannot get service instance \"" + rServiceName );
380 rxOut = Reference< T >::query( x );
381 if (! rxOut.is())
383 throw RuntimeException( "service instance \"" + rServiceName +
384 "\" does not support demanded interface \"" + cppu::UnoType<T>::get().getTypeName() );
389 inline static Sequence< OUString > getSupportedServiceNames()
391 OUString aName( SERVICENAME );
392 return Sequence< OUString >( &aName, 1 );
396 class TestImpl : public WeakImplHelper< XServiceInfo, XMain >
398 Reference< XMultiServiceFactory > _xSMgr;
400 Reference< XInterface > _xDirect;
401 Reference< XInterface > getDirect() throw (Exception);
402 Reference< XInterface > resolveObject( const OUString & rUnoUrl ) throw (Exception);
404 public:
405 explicit TestImpl( const Reference< XMultiServiceFactory > & xSMgr );
406 virtual ~TestImpl();
408 // XServiceInfo
409 virtual OUString SAL_CALL getImplementationName() throw (RuntimeException);
410 virtual sal_Bool SAL_CALL supportsService( const OUString & rServiceName ) throw (RuntimeException);
411 virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() throw (RuntimeException);
413 // XMain
414 virtual sal_Int32 SAL_CALL run( const Sequence< OUString > & rArgs ) throw (RuntimeException);
418 TestImpl::TestImpl( const Reference< XMultiServiceFactory > & xSMgr )
419 : _xSMgr( xSMgr )
423 TestImpl::~TestImpl()
428 static Reference< XInterface > SAL_CALL TestImpl_create( const Reference< XMultiServiceFactory > & xSMgr )
430 return Reference< XInterface >( *new TestImpl( xSMgr ) );
433 // XServiceInfo
435 OUString TestImpl::getImplementationName()
436 throw (RuntimeException)
438 return OUString( IMPLNAME );
441 sal_Bool TestImpl::supportsService( const OUString & rServiceName )
442 throw (RuntimeException)
444 return cppu::supportsService(this, rServiceName);
447 Sequence< OUString > TestImpl::getSupportedServiceNames()
448 throw (RuntimeException)
450 return benchmark_test::getSupportedServiceNames();
454 Reference< XInterface > TestImpl::getDirect()
455 throw (Exception)
457 if (! _xDirect.is())
459 MutexGuard aGuard( Mutex::getGlobalMutex() );
460 if (! _xDirect.is())
462 Reference< XSingleServiceFactory > xFac( loadLibComponentFactory(
463 OUString("perfobj"),
464 OUString("com.sun.star.comp.performance.PerformanceTestObject"),
465 _xSMgr, Reference< XRegistryKey >() ) );
466 if (! xFac.is())
467 throw RuntimeException("no test object available!" );
468 _xDirect = xFac->createInstance();
471 return _xDirect;
474 Reference< XInterface > TestImpl::resolveObject( const OUString & rUnoUrl )
475 throw (Exception)
477 Reference< XUnoUrlResolver > xResolver;
478 createInstance(
479 xResolver, _xSMgr,
480 OUString("com.sun.star.bridge.UnoUrlResolver") );
482 Reference< XInterface > xResolvedObject( xResolver->resolve( rUnoUrl ) );
484 if (! xResolvedObject.is())
486 throw RuntimeException( "cannot resolve object \"" + rUnoUrl + "\"!" );
489 return xResolvedObject;
493 class TimeEntry
495 sal_Int64 nLoop;
496 sal_uInt32 nTicks;
498 public:
499 TimeEntry()
501 TimeEntry( sal_Int64 nLoop_, sal_uInt32 nTicks_ )
502 : nLoop( nLoop_ )
503 , nTicks( nTicks_ )
506 inline double secPerCall() const
507 { return (((double)nTicks) / (nLoop * 1000)); }
509 double ratio( const TimeEntry & rEntry ) const;
512 double TimeEntry::ratio( const TimeEntry & rEntry ) const
514 double f = rEntry.nTicks * nLoop;
515 if (f == 0.0)
517 return 0.0;
519 else
521 return (((double)(nTicks * rEntry.nLoop)) / f);
526 typedef std::map< std::string, TimeEntry > t_TimeEntryMap;
529 struct TimingSheet
531 t_TimeEntryMap _entries;
532 void insert( const sal_Char * pText, sal_Int64 nLoop, sal_uInt32 nTicks );
535 void TimingSheet::insert( const sal_Char * pText, sal_Int64 nLoop, sal_uInt32 nTicks )
537 _entries[ pText ] = TimeEntry( nLoop, nTicks );
540 typedef std::unordered_map< std::string, TimingSheet > t_TimingSheetMap;
542 static void benchmark(
543 TimingSheet & rSheet, const Reference< XInterface > & xInstance, sal_Int64 nLoop )
544 throw (Exception)
546 Reference< XPerformanceTest > xBench( xInstance, UNO_QUERY_THROW );
548 sal_Int64 i;
549 sal_uInt32 tStart, tEnd;
551 const Type & rKnownType = cppu::UnoType<XPerformanceTest>::get();
552 const Type & rUnKnownType = cppu::UnoType<XSet>::get();
554 ComplexTypes aDummyStruct;
557 // oneway calls
558 i = nLoop;
559 tStart = getSystemTicks();
560 while (i--)
561 xBench->async();
562 sal_uInt32 tEndSend = getSystemTicks();
563 xBench->sync();
564 tEnd = getSystemTicks();
565 rSheet.insert( "1a: sending simple oneway calls (no params, no return)", nLoop, tEndSend - tStart );
566 rSheet.insert( "1b: simple oneway calls (no params, no return)", nLoop, tEnd - tStart );
567 // synchron calls
568 i = nLoop;
569 tStart = getSystemTicks();
570 while (i--)
571 xBench->sync();
572 xBench->sync();
573 tEnd = getSystemTicks();
574 rSheet.insert( "1c: simple synchron calls (no params no return)", nLoop+1, tEnd - tStart );
576 // acquire
577 i = nLoop;
578 tStart = getSystemTicks();
579 while (i--)
580 xBench->acquire();
581 tEnd = getSystemTicks();
582 rSheet.insert( "2a: interface acquire() calls", nLoop, tEnd - tStart );
583 // release
584 i = nLoop;
585 tStart = getSystemTicks();
586 while (i--)
587 xBench->release();
588 tEnd = getSystemTicks();
589 rSheet.insert( "2b: interface release() calls", nLoop, tEnd - tStart );
591 // queryInterface() for known type
592 i = nLoop;
593 tStart = getSystemTicks();
594 while (i--)
595 xBench->queryInterface( rKnownType );
596 tEnd = getSystemTicks();
597 rSheet.insert( "2c: interface query for implemented type", nLoop, tEnd - tStart );
598 // queryInterface() for unknown type
599 i = nLoop;
600 tStart = getSystemTicks();
601 while (i--)
602 xBench->queryInterface( rUnKnownType );
603 tEnd = getSystemTicks();
604 rSheet.insert( "2d: interface query for unknown type", nLoop, tEnd - tStart );
606 // create and forget objects
607 Reference< XPerformanceTest > xBench2( xBench );
608 i = nLoop;
609 tStart = getSystemTicks();
610 while (i--)
611 xBench2 = xBench2->createObject();
612 tEnd = getSystemTicks();
613 rSheet.insert( "3a: create and release test objects", nLoop, tEnd - tStart );
615 // hold new objects
616 Sequence< Reference< XInterface > > aSeq( nLoop / 100 );
617 Reference< XInterface > * pSeq = aSeq.getArray();
618 xBench2 = xBench;
619 i = aSeq.getLength();
620 tStart = getSystemTicks();
621 while (i--)
622 pSeq[i] = xBench2 = xBench2->createObject();
623 tEnd = getSystemTicks();
624 rSheet.insert( "3b: create and hold test objects", nLoop, tEnd - tStart );
626 // structs
627 i = nLoop;
628 tStart = getSystemTicks();
629 while (i--)
630 xBench->complex_in( aDummyStruct );
631 tEnd = getSystemTicks();
632 rSheet.insert( "4a: complex_in() calls (in struct; return struct)", nLoop, tEnd - tStart );
633 i = nLoop;
634 tStart = getSystemTicks();
635 while (i--)
636 xBench->complex_inout( aDummyStruct );
637 tEnd = getSystemTicks();
638 rSheet.insert( "4b: complex_inout() calls (inout struct; return struct)", nLoop, tEnd - tStart );
640 i = nLoop;
641 tStart = getSystemTicks();
642 while (i--)
643 xBench->complex_oneway( aDummyStruct );
644 tEnd = getSystemTicks();
645 rSheet.insert( "4c: complex_oneway() oneway calls (in struct)", nLoop, tEnd - tStart );
646 i = nLoop;
647 tStart = getSystemTicks();
648 while (i--)
649 xBench->complex_noreturn( aDummyStruct );
650 tEnd = getSystemTicks();
651 rSheet.insert( "4d: complex_noreturn() calls (in struct)", nLoop, tEnd - tStart );
653 // attributes, get() methods
654 i = nLoop;
655 tStart = getSystemTicks();
656 while (i--)
657 xBench->getLong();
658 tEnd = getSystemTicks();
659 rSheet.insert( "5a: getLong() call", nLoop, tEnd - tStart );
660 i = nLoop;
661 tStart = getSystemTicks();
662 while (i--)
663 xBench->getLong_attr();
664 tEnd = getSystemTicks();
665 rSheet.insert( "5b: get long attribute", nLoop, tEnd - tStart );
667 i = nLoop;
668 tStart = getSystemTicks();
669 while (i--)
670 xBench->setLong( 0 );
671 tEnd = getSystemTicks();
672 rSheet.insert( "5c: setLong() call", nLoop, tEnd - tStart );
673 i = nLoop;
674 tStart = getSystemTicks();
675 while (i--)
676 xBench->setLong_attr( 0 );
677 tEnd = getSystemTicks();
678 rSheet.insert( "5d: set long attribute", nLoop, tEnd - tStart );
680 i = nLoop;
681 tStart = getSystemTicks();
682 while (i--)
683 xBench->getHyper();
684 tEnd = getSystemTicks();
685 rSheet.insert( "5e: getHyper() call", nLoop, tEnd - tStart );
686 i = nLoop;
687 tStart = getSystemTicks();
688 while (i--)
689 xBench->getHyper_attr();
690 tEnd = getSystemTicks();
691 rSheet.insert( "5f: get hyper attribute", nLoop, tEnd - tStart );
693 i = nLoop;
694 tStart = getSystemTicks();
695 while (i--)
696 xBench->setHyper( 0 );
697 tEnd = getSystemTicks();
698 rSheet.insert( "5g: setHyper() call", nLoop, tEnd - tStart );
699 i = nLoop;
700 tStart = getSystemTicks();
701 while (i--)
702 xBench->setHyper_attr( 0 );
703 tEnd = getSystemTicks();
704 rSheet.insert( "5h: set hyper attribute", nLoop, tEnd - tStart );
706 i = nLoop;
707 tStart = getSystemTicks();
708 while (i--)
709 xBench->getFloat();
710 tEnd = getSystemTicks();
711 rSheet.insert( "5i: getFloat() call", nLoop, tEnd - tStart );
712 i = nLoop;
713 tStart = getSystemTicks();
714 while (i--)
715 xBench->getFloat_attr();
716 tEnd = getSystemTicks();
717 rSheet.insert( "5j: get float attribute",nLoop, tEnd - tStart );
719 i = nLoop;
720 tStart = getSystemTicks();
721 while (i--)
722 xBench->setFloat( 0.0 );
723 tEnd = getSystemTicks();
724 rSheet.insert( "5k: setFloat() call", nLoop, tEnd - tStart );
725 i = nLoop;
726 tStart = getSystemTicks();
727 while (i--)
728 xBench->setFloat_attr( 0.0 );
729 tEnd = getSystemTicks();
730 rSheet.insert( "5l: set float attribute", nLoop, tEnd - tStart );
732 i = nLoop;
733 tStart = getSystemTicks();
734 while (i--)
735 xBench->getDouble();
736 tEnd = getSystemTicks();
737 rSheet.insert( "5m: getDouble() call", nLoop, tEnd - tStart );
738 i = nLoop;
739 tStart = getSystemTicks();
740 while (i--)
741 xBench->getDouble_attr();
742 tEnd = getSystemTicks();
743 rSheet.insert( "5n: get double attribute", nLoop, tEnd - tStart );
744 i = nLoop;
745 tStart = getSystemTicks();
746 while (i--)
747 xBench->setDouble( 0.0 );
748 tEnd = getSystemTicks();
749 rSheet.insert( "5o: setDouble() call", nLoop, tEnd - tStart );
750 i = nLoop;
751 tStart = getSystemTicks();
752 while (i--)
753 xBench->setDouble_attr( 0.0 );
754 tEnd = getSystemTicks();
755 rSheet.insert( "5p: set double attribute", nLoop, tEnd - tStart );
757 i = nLoop;
758 tStart = getSystemTicks();
759 while (i--)
760 xBench->getString();
761 tEnd = getSystemTicks();
762 rSheet.insert( "6a: getString() call (empty)", nLoop, tEnd - tStart );
763 i = nLoop;
764 tStart = getSystemTicks();
765 while (i--)
766 xBench->getString_attr();
767 tEnd = getSystemTicks();
768 rSheet.insert( "6b: get empty string attribute", nLoop, tEnd - tStart );
770 i = nLoop;
771 OUString aDummyString;
772 tStart = getSystemTicks();
773 while (i--)
774 xBench->setString( aDummyString );
775 tEnd = getSystemTicks();
776 rSheet.insert( "6c: setString() call (empty)", nLoop, tEnd - tStart );
777 i = nLoop;
778 tStart = getSystemTicks();
779 while (i--)
780 xBench->setString_attr( aDummyString );
781 tEnd = getSystemTicks();
782 rSheet.insert( "6d: set empty string attribute", nLoop, tEnd - tStart );
784 i = nLoop;
785 tStart = getSystemTicks();
786 while (i--)
787 xBench->getInterface();
788 tEnd = getSystemTicks();
789 rSheet.insert( "7a: getInterface() call (null)", nLoop, tEnd - tStart );
790 i = nLoop;
791 tStart = getSystemTicks();
792 while (i--)
793 xBench->getInterface_attr();
794 tEnd = getSystemTicks();
795 rSheet.insert( "7b: get interface attribute", nLoop, tEnd - tStart );
797 i = nLoop;
798 Reference< XInterface > aDummyInterface;
799 tStart = getSystemTicks();
800 while (i--)
801 xBench->setInterface( aDummyInterface );
802 tEnd = getSystemTicks();
803 rSheet.insert( "7c: setInterface() call (null)", nLoop, tEnd - tStart );
804 i = nLoop;
805 tStart = getSystemTicks();
806 while (i--)
807 xBench->setInterface_attr( Reference< XInterface >() );
808 tEnd = getSystemTicks();
809 rSheet.insert( "7d: set interface attribute", nLoop, tEnd - tStart );
811 i = nLoop;
812 tStart = getSystemTicks();
813 while (i--)
814 xBench->getAny();
815 tEnd = getSystemTicks();
816 rSheet.insert( "8a: getAny() call (empty)", nLoop, tEnd - tStart );
817 i = nLoop;
818 tStart = getSystemTicks();
819 while (i--)
820 xBench->getAny_attr();
821 tEnd = getSystemTicks();
822 rSheet.insert( "8b: get empty any attribute", nLoop, tEnd - tStart );
824 i = nLoop;
825 Any aDummyAny;
826 tStart = getSystemTicks();
827 while (i--)
828 xBench->setAny( aDummyAny );
829 tEnd = getSystemTicks();
830 rSheet.insert( "8c: setAny() call (empty)", nLoop, tEnd - tStart );
831 i = nLoop;
832 tStart = getSystemTicks();
833 while (i--)
834 xBench->setAny_attr( aDummyAny );
835 tEnd = getSystemTicks();
836 rSheet.insert( "8d: set empty any attribute", nLoop, tEnd - tStart );
838 i = nLoop;
839 tStart = getSystemTicks();
840 while (i--)
841 xBench->getSequence();
842 tEnd = getSystemTicks();
843 rSheet.insert( "9a: getSequence() call (empty)", nLoop, tEnd - tStart );
844 i = nLoop;
845 tStart = getSystemTicks();
846 while (i--)
847 xBench->getSequence_attr();
848 tEnd = getSystemTicks();
849 rSheet.insert( "9b: get empty sequence attribute", nLoop, tEnd - tStart );
850 i = nLoop;
851 Sequence< Reference< XInterface > > aDummySeq;
852 tStart = getSystemTicks();
853 while (i--)
854 xBench->setSequence( aDummySeq );
855 tEnd = getSystemTicks();
856 rSheet.insert( "9c: setSequence() call (empty)", nLoop, tEnd - tStart );
857 i = nLoop;
858 tStart = getSystemTicks();
859 while (i--)
860 xBench->setSequence_attr( aDummySeq );
861 tEnd = getSystemTicks();
862 rSheet.insert( "9d: set empty sequence attribute", nLoop, tEnd - tStart );
864 i = nLoop;
865 tStart = getSystemTicks();
866 while (i--)
867 xBench->getStruct();
868 tEnd = getSystemTicks();
869 rSheet.insert( "Aa: getStruct() call", nLoop, tEnd - tStart );
870 i = nLoop;
871 tStart = getSystemTicks();
872 while (i--)
873 xBench->getStruct_attr();
874 tEnd = getSystemTicks();
875 rSheet.insert( "Ab: get struct attribute", nLoop, tEnd - tStart );
877 i = nLoop;
878 tStart = getSystemTicks();
879 while (i--)
880 xBench->setStruct( aDummyStruct );
881 tEnd = getSystemTicks();
882 rSheet.insert( "Ac: setStruct() call", nLoop, tEnd - tStart );
883 i = nLoop;
884 tStart = getSystemTicks();
885 while (i--)
886 xBench->setStruct_attr( aDummyStruct );
887 tEnd = getSystemTicks();
888 rSheet.insert( "Ad: set struct attribute", nLoop, tEnd - tStart );
890 // load
891 // i = nLoop;
892 // tStart = getSystemTicks();
893 // while (i--)
894 // xBench->setSequence( aSeq );
895 // tEnd = getSystemTicks();
896 // rSheet.insert( "transfer of existing objects", nLoop, tEnd - tStart );
898 // exceptions
899 i = nLoop;
900 tStart = getSystemTicks();
901 while (i--)
905 xBench->raiseRuntimeException();
907 catch (RuntimeException &)
911 tEnd = getSystemTicks();
912 rSheet.insert( "Ba: raising RuntimeException", nLoop, tEnd - tStart );
918 static OUString extractParam( const Sequence< OUString > & rArgs, const OUString & rParam )
920 const OUString * pArgs = rArgs.getConstArray();
921 for ( sal_Int32 nPos = rArgs.getLength(); nPos--; )
923 if (pArgs[nPos].startsWith( rParam ) &&
924 pArgs[nPos].getLength() > (rParam.getLength()+1))
926 return pArgs[nPos].copy( rParam.getLength() +1 ); // XXX=bla
929 return OUString();
932 const sal_Int32 nMagicNumberDirect = 34000;
934 //XMain
936 sal_Int32 TestImpl::run( const Sequence< OUString > & rArgs )
937 throw (RuntimeException)
939 // defaults
940 FILE * stream = stderr;
941 sal_Int64 nLoop = NLOOP;
942 OUString aArg("dms");
946 OUString aLoopStr( extractParam( rArgs, OUString("loop") ) );
947 if (aLoopStr.getLength())
949 sal_Int64 n = aLoopStr.toInt64();
950 if (n > 0)
951 nLoop = n;
954 OUString aDurationStr( extractParam( rArgs , OUString("duration" ) ) );
955 if( aDurationStr.getLength() )
957 sal_Int64 n = aDurationStr.toInt64();
958 if( n >0 )
959 nLoop = nMagicNumberDirect * n;
962 OUString aLogStr( extractParam( rArgs, OUString("log") ) );
963 if (aLogStr.getLength())
965 if (aLogStr.equalsAscii( "stderr" ) )
967 stream = stderr;
969 else if (aLogStr.equalsAscii( "stdout" ) )
971 stream = stdout;
973 else
975 OString aFileName( OUStringToOString( aLogStr, RTL_TEXTENCODING_ASCII_US ) );
976 stream = ::fopen( aFileName.getStr(), "w" );
977 if (! stream)
979 throw RuntimeException( "cannot open file for writing: \"" + aLogStr + "\"!" );
984 OUString aArgStr( extractParam( rArgs, OUString("opt") ) );
985 if (aArgStr.getLength())
987 aArg = aArgStr;
990 if (! rArgs.getLength())
991 out( "\n> no options given, using defaults" );
993 // params
994 out( "\n> opt=" );
995 out( aArg );
996 out( " log=" );
997 if (stream == stderr)
998 out( "stderr" );
999 else if (stream == stdout)
1000 out( "stdout loop=" );
1001 else
1002 out( aLogStr );
1003 out( " loop=" );
1004 out( nLoop );
1005 out( "\n" );
1006 t_TimingSheetMap aSheets;
1007 TimingSheet aDirect;
1010 if (aArg.indexOf( 'd' ) >= 0)
1012 // in process direct test
1013 sal_uInt32 nStart = getSystemTicks();
1014 benchmark( aDirect, getDirect(), nLoop );
1015 sal_uInt32 nEnd = getSystemTicks();
1016 fprintf( stderr, "Duration (direct in process): %g s\n", (nEnd - nStart)/1000. );
1020 if (aArg.indexOf( 'm' ) >= 0)
1022 // in process uno dispatch
1023 Environment aCppEnv, aAnoCppEnv;
1024 OUString aCurrentLanguageBindingName( CPPU_CURRENT_LANGUAGE_BINDING_NAME );
1025 uno_getEnvironment( reinterpret_cast< uno_Environment ** >( &aCppEnv ),
1026 aCurrentLanguageBindingName.pData, 0 );
1027 // anonymous
1028 uno_createEnvironment( reinterpret_cast< uno_Environment ** >( &aAnoCppEnv ),
1029 aCurrentLanguageBindingName.pData, 0 );
1031 // pseudo mapping uno<->uno: does nothing!
1032 Mapping aMapping( aCppEnv.get(), aAnoCppEnv.get(), OUString("pseudo") );
1033 if (! aMapping.is())
1034 throw RuntimeException("no pseudo mapping available!" );
1036 Reference< XInterface > xMapped;
1037 Reference< XInterface > xDirect( getDirect() );
1038 aMapping.mapInterface( reinterpret_cast< void ** >( &xMapped ), xDirect.get(),
1039 cppu::UnoType<decltype(xDirect)>::get() );
1040 if (! xMapped.is())
1041 throw RuntimeException("mapping object failed!" );
1043 sal_uInt32 nStart = getSystemTicks();
1044 benchmark( aSheets[ "mapped in process" ], xMapped, nLoop / 100 );
1045 sal_uInt32 nEnd = getSystemTicks();
1046 fprintf( stderr, "Duration (mapped in process): %g s\n", (nStart - nEnd)/1000. );
1050 if (aArg.indexOf( 's' ) >= 0)
1052 // start server process
1053 oslSecurity hSecurity = osl_getCurrentSecurity();
1054 if (! hSecurity)
1055 throw RuntimeException("cannot get current security handle!" );
1057 OUString aArgs[] = {
1058 OUString("-c"),
1059 OUString("com.sun.star.comp.performance.PerformanceTestObject"),
1060 OUString("-l"),
1061 #ifdef SAL_UNX
1062 OUString("libperfobj.so"),
1063 #else
1064 OUString("perfobj.dll"),
1065 #endif
1066 OUString("-r"),
1067 OUString("applicat.rdb"),
1068 OUString("-u"),
1069 OUString("uno:socket,host=localhost,port=6000;iiop;TestRemoteObject"),
1070 OUString("--singleaccept")
1072 rtl_uString * pArgs[] = {
1073 aArgs[0].pData,
1074 aArgs[1].pData,
1075 aArgs[2].pData,
1076 aArgs[3].pData,
1077 aArgs[4].pData,
1078 aArgs[5].pData,
1079 aArgs[6].pData,
1080 aArgs[7].pData,
1081 aArgs[8].pData,
1084 out( "\n> executing: \"uno" );
1085 for ( sal_Int32 nPos = 0; nPos < (sizeof(aArgs) / sizeof(OUString)); ++nPos )
1087 out( " " );
1088 out( aArgs[nPos] );
1090 out( "\" ..." );
1092 oslProcess hProcess = 0;
1093 OUString aUnoExe("uno");
1094 OUString aWorkingDir(".");
1095 osl_executeProcess(
1096 aUnoExe.pData, pArgs, sizeof(aArgs) / sizeof(OUString),
1097 osl_Process_SEARCHPATH | osl_Process_DETACHED | osl_Process_NORMAL,
1098 hSecurity, aWorkingDir.pData, 0, 0, &hProcess );
1100 osl_freeSecurityHandle( hSecurity );
1101 if (! hProcess)
1102 throw RuntimeException("cannot start server process!" );
1103 osl_freeProcessHandle( hProcess );
1105 // wait three seconds
1106 TimeValue threeSeconds;
1107 threeSeconds.Seconds = 3;
1108 osl_waitThread( &threeSeconds );
1110 // connect and resolve outer process object
1111 Reference< XInterface > xResolvedObject( resolveObject( OUString("uno:socket,host=localhost,port=6000;iiop;TestRemoteObject") ) );
1113 benchmark( aSheets[ "remote same host" ], xResolvedObject, nLoop / 300 );
1117 if (aArg.indexOf( 'r' ) >= 0)
1119 // remote
1120 OUString aUnoUrl( extractParam( rArgs, OUString("url") ) );
1121 if (! aUnoUrl.getLength())
1122 throw RuntimeException( "performance test r(emote) needs additional uno url!" );
1124 // connect and resolve outer process object
1125 Reference< XInterface > xResolvedObject( resolveObject( aUnoUrl ) );
1127 sal_Int32 t1 = getSystemTicks();
1128 OString o = OUStringToOString( aUnoUrl, RTL_TEXTENCODING_ASCII_US );
1129 benchmark( aSheets[ o.getStr() ], xResolvedObject, nLoop / 900 );
1130 sal_Int32 t2 = getSystemTicks();
1131 fprintf( stderr, "Duration (%s): %g s\n", o.getStr(),(t2 - t1)/1000. );
1135 if (aArg.indexOf( 'j' ) >= 0)
1137 // java
1138 benchmark( aSheets[ "java in process" ],
1139 _xSMgr->createInstance("com.sun.star.comp.benchmark.JavaTestObject"),
1140 nLoop / 1000 );
1144 // dump out tables
1146 out( "\nTimes( ratio to direct in process )", stream );
1147 out( ":", stream );
1149 sal_Int32 nPos = 60;
1150 out( "[direct in process]", stream, nPos );
1151 t_TimingSheetMap::const_iterator iSheets( aSheets.begin() );
1152 for ( ; iSheets != aSheets.end(); ++iSheets )
1154 nPos += 40;
1155 out( "[", stream, nPos );
1156 out( (*iSheets).first.c_str(), stream );
1157 out( "]", stream );
1159 for ( t_TimeEntryMap::const_iterator iTopics( aDirect._entries.begin() );
1160 iTopics != aDirect._entries.end(); ++iTopics )
1162 const std::string & rTopic = (*iTopics).first;
1164 out( "\n", stream );
1165 out( rTopic.c_str(), stream );
1167 out( ":", stream, 58, '.' );
1169 sal_Int32 nPos = 60;
1171 double secs = (*iTopics).second.secPerCall();
1172 if (secs > 0.0)
1174 out( secs * 1000, stream, nPos );
1175 out( "ms", stream );
1177 else
1179 out( "NA", stream, nPos );
1182 iSheets = aSheets.begin();
1183 for ( ; iSheets != aSheets.end(); ++iSheets )
1185 const t_TimeEntryMap::const_iterator iFind( (*iSheets).second._entries.find( rTopic ) );
1186 OSL_ENSURE( iFind != (*iSheets).second._entries.end(), "####" );
1188 nPos += 40;
1190 double secs = (*iFind).second.secPerCall();
1191 if (secs != 0.0)
1193 out( secs * 1000, stream, nPos );
1194 out( "ms", stream );
1196 out( " (", stream );
1197 double ratio = (*iFind).second.ratio( (*iTopics).second );
1198 if (ratio != 0.0)
1200 out( ratio, stream );
1201 out( " x)", stream );
1203 else
1205 out( "NA)", stream );
1208 else
1210 out( "NA", stream, nPos );
1215 catch (Exception & rExc)
1217 if (stream != stderr && stream != stdout)
1218 ::fclose( stream );
1219 throw RuntimeException( rExc.Message, rExc.Context );
1222 if (stream != stderr && stream != stdout)
1223 ::fclose( stream );
1225 out( "\n> done.\n" );
1226 return 0;
1232 extern "C"
1235 sal_Bool SAL_CALL component_writeInfo(
1236 void * pServiceManager, void * pRegistryKey )
1238 if (pRegistryKey)
1242 Reference< XRegistryKey > xNewKey(
1243 reinterpret_cast< XRegistryKey * >( pRegistryKey )->createKey(
1244 OUString( "/" IMPLNAME "/UNO/SERVICES" ) ) );
1245 xNewKey->createKey( OUString( SERVICENAME ) );
1247 return sal_True;
1249 catch (InvalidRegistryException &)
1251 OSL_FAIL( "### InvalidRegistryException!" );
1254 return sal_False;
1257 SAL_DLLPUBLIC_EXPORT void * SAL_CALL component_getFactory(
1258 const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey )
1260 void * pRet = 0;
1262 if (pServiceManager && rtl_str_compare( pImplName, IMPLNAME ) == 0)
1264 Reference< XSingleServiceFactory > xFactory( createSingleFactory(
1265 reinterpret_cast< XMultiServiceFactory * >( pServiceManager ),
1266 OUString( IMPLNAME ),
1267 benchmark_test::TestImpl_create,
1268 benchmark_test::getSupportedServiceNames() ) );
1270 if (xFactory.is())
1272 xFactory->acquire();
1273 pRet = xFactory.get();
1277 return pRet;
1281 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */