Branch libreoffice-5-0-4
[LibreOffice.git] / testtools / source / performance / ubtest.cxx
blobf1eabf2f7a8c582350b2b9fb6265026c43870316
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 SAL_W32
36 #include <windows.h>
37 #else
38 #include <sys/times.h>
39 #include <unistd.h>
40 #endif
42 #include <rtl/string.hxx>
43 #include <rtl/strbuf.hxx>
44 #include <rtl/ustrbuf.hxx>
46 #include <uno/environment.hxx>
47 #include <uno/lbnames.h>
48 #include <uno/mapping.hxx>
50 #include <cppuhelper/factory.hxx>
51 #include <cppuhelper/implbase2.hxx>
53 #include <com/sun/star/lang/XServiceInfo.hpp>
54 #include <com/sun/star/lang/XComponent.hpp>
55 #include <com/sun/star/lang/XMain.hpp>
56 #include <com/sun/star/lang/XInitialization.hpp>
57 #include <com/sun/star/loader/XImplementationLoader.hpp>
58 #include <com/sun/star/registry/XRegistryKey.hpp>
59 #include <com/sun/star/bridge/XUnoUrlResolver.hpp>
60 #include <com/sun/star/container/XSet.hpp>
61 #include <com/sun/star/test/performance/XPerformanceTest.hpp>
63 #define NLOOP 200000000
65 using namespace osl;
66 using namespace cppu;
67 using namespace com::sun::star::uno;
68 using namespace com::sun::star::lang;
69 using namespace com::sun::star::loader;
70 using namespace com::sun::star::registry;
71 using namespace com::sun::star::bridge;
72 using namespace com::sun::star::container;
73 using namespace com::sun::star::test::performance;
76 #define SERVICENAME "com.sun.star.test.performance.PerformanceTest"
77 #define IMPLNAME "com.sun.star.comp.performance.PerformanceTest"
79 namespace benchmark_test
82 static inline sal_uInt32 getSystemTicks()
84 #ifdef SAL_W32
85 return (sal_uInt32)GetTickCount();
86 #else // only UNX supported for now
87 static sal_uInt32 nImplTicksPerSecond = 0;
88 static double dImplTicksPerSecond;
89 static double dImplTicksULONGMAX;
91 struct tms aTms;
92 sal_uInt32 nTicks = (sal_uInt32)times( &aTms );
94 if ( !nImplTicksPerSecond )
96 nImplTicksPerSecond = sysconf(_SC_CLK_TCK);
97 dImplTicksPerSecond = nImplTicksPerSecond;
98 dImplTicksULONGMAX = (double)(sal_uInt32)ULONG_MAX;
101 double fTicks = nTicks;
102 fTicks *= 1000;
103 fTicks /= dImplTicksPerSecond;
104 fTicks = fmod (fTicks, dImplTicksULONGMAX);
106 return (sal_uInt32)fTicks;
107 #endif
111 static void out( const sal_Char * pText, FILE * stream = stderr,
112 sal_Int32 nStart = -1, sal_Char cFillchar = ' ' )
114 static sal_Int32 s_nPos = 0;
116 sal_Char ar[2] = { cFillchar, 0 };
117 while (s_nPos < nStart)
119 ::fprintf( stream, ar );
120 ++s_nPos;
123 ::fprintf( stream, pText );
125 for ( const sal_Char * p = pText; *p; ++p )
127 if (*p == '\n')
128 s_nPos = 0;
129 else
130 ++s_nPos;
134 static inline void out( const OUString & rText, FILE * stream = stderr,
135 sal_Int32 nStart = -1, sal_Char cFillchar = ' ' )
137 OString aText( OUStringToOString( rText, RTL_TEXTENCODING_ASCII_US ) );
138 out( aText.getStr(), stream, nStart, cFillchar );
141 static inline void out( double fVal, FILE * stream = stderr,
142 sal_Int32 nStart = -1, sal_Char cFillchar = ' ' )
144 sal_Char ar[128];
145 ::snprintf( ar, sizeof(ar), (fVal < 0.000001 ? "%g" : "%f"), fVal );
146 out( ar, stream, nStart, cFillchar );
149 static inline void out( sal_Int64 nVal, FILE * stream = stderr,
150 sal_Int32 nStart = -1, sal_Char cFillchar = ' ' )
152 sal_Char ar[128];
153 ::snprintf( ar, sizeof(ar), "%ld", nVal );
154 out( ar, stream, nStart, cFillchar );
158 Reference< XSingleServiceFactory > loadLibComponentFactory(
159 const OUString & rLibName, const OUString & rImplName,
160 const Reference< XMultiServiceFactory > & xSF, const Reference< XRegistryKey > & xKey )
162 Reference< XSingleServiceFactory > xRet;
164 OUStringBuffer aLibNameBuf( 32 );
165 #ifdef SAL_UNX
166 aLibNameBuf.append( "lib" );
167 aLibNameBuf.append( rLibName );
168 aLibNameBuf.append( ".so" );
169 #else
170 aLibNameBuf.append( rLibName );
171 aLibNameBuf.append( ".dll" );
172 #endif
173 OUString aLibName( aLibNameBuf.makeStringAndClear() );
174 oslModule lib = osl_loadModule( aLibName.pData, SAL_LOADMODULE_LAZY | SAL_LOADMODULE_GLOBAL );
176 if (lib)
178 void * pSym;
180 // ========================= LATEST VERSION =========================
181 OUString aGetEnvName( COMPONENT_GETENV );
182 if (pSym = osl_getSymbol( lib, aGetEnvName.pData ))
184 uno_Environment * pCurrentEnv = 0;
185 uno_Environment * pEnv = 0;
186 const sal_Char * pEnvTypeName = 0;
187 (*((component_getImplementationEnvironmentFunc)pSym))( &pEnvTypeName, &pEnv );
189 sal_Bool bNeedsMapping =
190 (pEnv || 0 != rtl_str_compare( pEnvTypeName, CPPU_CURRENT_LANGUAGE_BINDING_NAME ));
192 OUString aEnvTypeName( OUString::createFromAscii( pEnvTypeName ) );
194 if (bNeedsMapping)
196 if (! pEnv)
197 uno_getEnvironment( &pEnv, aEnvTypeName.pData, 0 );
198 if (pEnv)
200 OUString aCppEnvTypeName( CPPU_CURRENT_LANGUAGE_BINDING_NAME );
201 uno_getEnvironment( &pCurrentEnv, aCppEnvTypeName.pData, 0 );
202 if (pCurrentEnv)
203 bNeedsMapping = (pEnv != pCurrentEnv);
207 OUString aGetFactoryName( COMPONENT_GETFACTORY );
208 if (pSym = osl_getSymbol( lib, aGetFactoryName.pData ))
210 OString aImplName( OUStringToOString( rImplName, RTL_TEXTENCODING_ASCII_US ) );
212 if (bNeedsMapping)
214 if (pEnv && pCurrentEnv)
216 Mapping aCurrent2Env( pCurrentEnv, pEnv );
217 Mapping aEnv2Current( pEnv, pCurrentEnv );
219 if (aCurrent2Env.is() && aEnv2Current.is())
221 void * pSMgr = aCurrent2Env.mapInterface(
222 xSF.get(), cppu::UnoType<XMultiServiceFactory>::get() );
223 void * pKey = aCurrent2Env.mapInterface(
224 xKey.get(), cppu::UnoType<XRegistryKey>::get() );
226 void * pSSF = (*((component_getFactoryFunc)pSym))(
227 aImplName.getStr(), pSMgr, pKey );
229 if (pKey)
230 (*pEnv->pExtEnv->releaseInterface)( pEnv->pExtEnv, pKey );
231 if (pSMgr)
232 (*pEnv->pExtEnv->releaseInterface)( pEnv->pExtEnv, pSMgr );
234 if (pSSF)
236 aEnv2Current.mapInterface(
237 reinterpret_cast< void ** >( &xRet ),
238 pSSF, cppu::UnoType<XSingleServiceFactory>::get() );
239 (*pEnv->pExtEnv->releaseInterface)( pEnv->pExtEnv, pSSF );
244 else
246 XSingleServiceFactory * pRet = (XSingleServiceFactory *)
247 (*((component_getFactoryFunc)pSym))(
248 aImplName.getStr(), xSF.get(), xKey.get() );
249 if (pRet)
251 xRet = pRet;
252 pRet->release();
257 if (pEnv)
258 (*pEnv->release)( pEnv );
259 if (pCurrentEnv)
260 (*pCurrentEnv->release)( pCurrentEnv );
263 // ========================= PREVIOUS VERSION =========================
264 else
266 OUString aGetFactoryName( CREATE_COMPONENT_FACTORY_FUNCTION );
267 if (pSym = osl_getSymbol( lib, aGetFactoryName.pData ))
269 OUString aCppEnvTypeName( CPPU_CURRENT_LANGUAGE_BINDING_NAME );
270 OUString aUnoEnvTypeName( UNO_LB_UNO );
271 Mapping aUno2Cpp( aUnoEnvTypeName, aCppEnvTypeName );
272 Mapping aCpp2Uno( aCppEnvTypeName, aUnoEnvTypeName );
273 OSL_ENSURE( aUno2Cpp.is() && aCpp2Uno.is(), "### cannot get uno mappings!" );
275 if (aUno2Cpp.is() && aCpp2Uno.is())
277 uno_Interface * pUComponentFactory = 0;
279 uno_Interface * pUSFactory = (uno_Interface *)aCpp2Uno.mapInterface(
280 xSF.get(), cppu::UnoType<XMultiServiceFactory>::get() );
281 uno_Interface * pUKey = (uno_Interface *)aCpp2Uno.mapInterface(
282 xKey.get(), cppu::UnoType<XRegistryKey>::get() );
284 pUComponentFactory = (*((CreateComponentFactoryFunc)pSym))(
285 rImplName.getStr(), pUSFactory, pUKey );
287 if (pUKey)
288 (*pUKey->release)( pUKey );
289 if (pUSFactory)
290 (*pUSFactory->release)( pUSFactory );
292 if (pUComponentFactory)
294 XSingleServiceFactory * pXFactory =
295 (XSingleServiceFactory *)aUno2Cpp.mapInterface(
296 pUComponentFactory, cppu::UnoType<XSingleServiceFactory>::get() );
297 (*pUComponentFactory->release)( pUComponentFactory );
299 if (pXFactory)
301 xRet = pXFactory;
302 pXFactory->release();
309 if (! xRet.is())
310 osl_unloadModule( lib );
313 return xRet;
316 template< class T >
317 static void createInstance( Reference< T > & rxOut,
318 const Reference< XMultiServiceFactory > & xMgr,
319 const OUString & rServiceName )
320 throw (RuntimeException)
322 Reference< XInterface > x( xMgr->createInstance( rServiceName ), UNO_QUERY );
324 if (! x.is())
326 static sal_Bool s_bSet = sal_False;
327 if (! s_bSet)
329 MutexGuard aGuard( Mutex::getGlobalMutex() );
330 if (! s_bSet)
332 Reference< XSet > xSet( xMgr, UNO_QUERY );
333 if (xSet.is())
335 // acceptor
336 xSet->insert( makeAny( loadLibComponentFactory(
337 OUString("acceptor"),
338 OUString("com.sun.star.comp.stoc.Acceptor"),
339 xMgr, Reference< XRegistryKey >() ) ) );
340 // connector
341 xSet->insert( makeAny( loadLibComponentFactory(
342 OUString("connectr"),
343 OUString("com.sun.star.comp.stoc.Connector"),
344 xMgr, Reference< XRegistryKey >() ) ) );
345 // iiop bridge
346 xSet->insert( makeAny( loadLibComponentFactory(
347 OUString("remotebridge"),
348 OUString("com.sun.star.bridge.Bridge.various"),
349 xMgr, Reference< XRegistryKey >() ) ) );
350 // bridge factory
351 xSet->insert( makeAny( loadLibComponentFactory(
352 OUString("brdgfctr"),
353 OUString("com.sun.star.comp.stoc.BridgeFactory"),
354 xMgr, Reference< XRegistryKey >() ) ) );
355 // uno url resolver
356 xSet->insert( makeAny( loadLibComponentFactory(
357 OUString("uuresolver"),
358 OUString("com.sun.star.comp.bridge.UnoUrlResolver"),
359 xMgr, Reference< XRegistryKey >() ) ) );
360 // java loader
361 // xSet->insert( makeAny( loadLibComponentFactory(
362 // OUString("javaloader"),
363 // OUString("com.sun.star.comp.stoc.JavaComponentLoader"),
364 // xMgr, Reference< XRegistryKey >() ) ) );
366 s_bSet = sal_True;
369 x = xMgr->createInstance( rServiceName );
372 if (! x.is())
374 OUStringBuffer buf( 64 );
375 buf.append( "cannot get service instance \"" );
376 buf.append( rServiceName );
377 buf.append( "\"!" );
378 throw RuntimeException( buf.makeStringAndClear() );
381 rxOut = Reference< T >::query( x );
382 if (! rxOut.is())
384 OUStringBuffer buf( 64 );
385 buf.append( "service instance \"" );
386 buf.append( rServiceName );
387 buf.append( "\" does not support demanded interface \"" );
388 const Type & rType = cppu::UnoType<T>::get();
389 buf.append( rType.getTypeName() );
390 buf.append( "\"!" );
391 throw RuntimeException( buf.makeStringAndClear() );
396 inline static Sequence< OUString > getSupportedServiceNames()
398 OUString aName( SERVICENAME );
399 return Sequence< OUString >( &aName, 1 );
403 class TestImpl : public WeakImplHelper2< XServiceInfo, XMain >
405 Reference< XMultiServiceFactory > _xSMgr;
407 Reference< XInterface > _xDirect;
408 Reference< XInterface > getDirect() throw (Exception);
409 Reference< XInterface > resolveObject( const OUString & rUnoUrl ) throw (Exception);
411 public:
412 TestImpl( const Reference< XMultiServiceFactory > & xSMgr );
413 virtual ~TestImpl();
415 // XServiceInfo
416 virtual OUString SAL_CALL getImplementationName() throw (RuntimeException);
417 virtual sal_Bool SAL_CALL supportsService( const OUString & rServiceName ) throw (RuntimeException);
418 virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() throw (RuntimeException);
420 // XMain
421 virtual sal_Int32 SAL_CALL run( const Sequence< OUString > & rArgs ) throw (RuntimeException);
427 TestImpl::TestImpl( const Reference< XMultiServiceFactory > & xSMgr )
428 : _xSMgr( xSMgr )
432 TestImpl::~TestImpl()
437 static Reference< XInterface > SAL_CALL TestImpl_create( const Reference< XMultiServiceFactory > & xSMgr )
439 return Reference< XInterface >( *new TestImpl( xSMgr ) );
442 // XServiceInfo
444 OUString TestImpl::getImplementationName()
445 throw (RuntimeException)
447 return OUString( IMPLNAME );
450 sal_Bool TestImpl::supportsService( const OUString & rServiceName )
451 throw (RuntimeException)
453 return cppu::supportsService(this, rServiceName);
456 Sequence< OUString > TestImpl::getSupportedServiceNames()
457 throw (RuntimeException)
459 return benchmark_test::getSupportedServiceNames();
463 Reference< XInterface > TestImpl::getDirect()
464 throw (Exception)
466 if (! _xDirect.is())
468 MutexGuard aGuard( Mutex::getGlobalMutex() );
469 if (! _xDirect.is())
471 Reference< XSingleServiceFactory > xFac( loadLibComponentFactory(
472 OUString("perfobj"),
473 OUString("com.sun.star.comp.performance.PerformanceTestObject"),
474 _xSMgr, Reference< XRegistryKey >() ) );
475 if (! xFac.is())
476 throw RuntimeException("no test object available!" );
477 _xDirect = xFac->createInstance();
480 return _xDirect;
483 Reference< XInterface > TestImpl::resolveObject( const OUString & rUnoUrl )
484 throw (Exception)
486 Reference< XUnoUrlResolver > xResolver;
487 createInstance(
488 xResolver, _xSMgr,
489 OUString("com.sun.star.bridge.UnoUrlResolver") );
491 Reference< XInterface > xResolvedObject( xResolver->resolve( rUnoUrl ) );
493 if (! xResolvedObject.is())
495 OUStringBuffer buf( 32 );
496 buf.append( "cannot resolve object \"" );
497 buf.append( rUnoUrl );
498 buf.append( "\"!" );
499 throw RuntimeException( buf.makeStringAndClear() );
502 return xResolvedObject;
506 class TimeEntry
508 sal_Int64 nLoop;
509 sal_uInt32 nTicks;
511 public:
512 TimeEntry()
514 TimeEntry( sal_Int64 nLoop_, sal_uInt32 nTicks_ )
515 : nLoop( nLoop_ )
516 , nTicks( nTicks_ )
519 inline double secPerCall() const
520 { return (((double)nTicks) / (nLoop * 1000)); }
522 double ratio( const TimeEntry & rEntry ) const;
525 double TimeEntry::ratio( const TimeEntry & rEntry ) const
527 double f = rEntry.nTicks * nLoop;
528 if (f == 0.0)
530 return 0.0;
532 else
534 return (((double)(nTicks * rEntry.nLoop)) / f);
539 typedef std::map< std::string, TimeEntry > t_TimeEntryMap;
542 struct TimingSheet
544 t_TimeEntryMap _entries;
545 void insert( const sal_Char * pText, sal_Int64 nLoop, sal_uInt32 nTicks );
548 void TimingSheet::insert( const sal_Char * pText, sal_Int64 nLoop, sal_uInt32 nTicks )
550 _entries[ pText ] = TimeEntry( nLoop, nTicks );
553 typedef std::unordered_map< std::string, TimingSheet > t_TimingSheetMap;
555 static void benchmark(
556 TimingSheet & rSheet, const Reference< XInterface > & xInstance, sal_Int64 nLoop )
557 throw (Exception)
559 Reference< XPerformanceTest > xBench( xInstance, UNO_QUERY );
560 if (! xBench.is())
561 throw RuntimeException("illegal test object!" );
563 sal_Int64 i;
564 sal_uInt32 tStart, tEnd;
566 const Type & rKnownType = cppu::UnoType<XPerformanceTest>::get();
567 const Type & rUnKnownType = cppu::UnoType<XSet>::get();
569 ComplexTypes aDummyStruct;
572 // oneway calls
573 i = nLoop;
574 tStart = getSystemTicks();
575 while (i--)
576 xBench->async();
577 sal_uInt32 tEndSend = getSystemTicks();
578 xBench->sync();
579 tEnd = getSystemTicks();
580 rSheet.insert( "1a: sending simple oneway calls (no params, no return)", nLoop, tEndSend - tStart );
581 rSheet.insert( "1b: simple oneway calls (no params, no return)", nLoop, tEnd - tStart );
582 // synchron calls
583 i = nLoop;
584 tStart = getSystemTicks();
585 while (i--)
586 xBench->sync();
587 xBench->sync();
588 tEnd = getSystemTicks();
589 rSheet.insert( "1c: simple synchron calls (no params no return)", nLoop+1, tEnd - tStart );
591 // acquire
592 i = nLoop;
593 tStart = getSystemTicks();
594 while (i--)
595 xBench->acquire();
596 tEnd = getSystemTicks();
597 rSheet.insert( "2a: interface acquire() calls", nLoop, tEnd - tStart );
598 // release
599 i = nLoop;
600 tStart = getSystemTicks();
601 while (i--)
602 xBench->release();
603 tEnd = getSystemTicks();
604 rSheet.insert( "2b: interface release() calls", nLoop, tEnd - tStart );
606 // queryInterface() for known type
607 i = nLoop;
608 tStart = getSystemTicks();
609 while (i--)
610 xBench->queryInterface( rKnownType );
611 tEnd = getSystemTicks();
612 rSheet.insert( "2c: interface query for implemented type", nLoop, tEnd - tStart );
613 // queryInterface() for unknown type
614 i = nLoop;
615 tStart = getSystemTicks();
616 while (i--)
617 xBench->queryInterface( rUnKnownType );
618 tEnd = getSystemTicks();
619 rSheet.insert( "2d: interface query for unknown type", nLoop, tEnd - tStart );
621 // create and forget objects
622 Reference< XPerformanceTest > xBench2( xBench );
623 i = nLoop;
624 tStart = getSystemTicks();
625 while (i--)
626 xBench2 = xBench2->createObject();
627 tEnd = getSystemTicks();
628 rSheet.insert( "3a: create and release test objects", nLoop, tEnd - tStart );
630 // hold new objects
631 Sequence< Reference< XInterface > > aSeq( nLoop / 100 );
632 Reference< XInterface > * pSeq = aSeq.getArray();
633 xBench2 = xBench;
634 i = aSeq.getLength();
635 tStart = getSystemTicks();
636 while (i--)
637 pSeq[i] = xBench2 = xBench2->createObject();
638 tEnd = getSystemTicks();
639 rSheet.insert( "3b: create and hold test objects", nLoop, tEnd - tStart );
641 // structs
642 i = nLoop;
643 tStart = getSystemTicks();
644 while (i--)
645 xBench->complex_in( aDummyStruct );
646 tEnd = getSystemTicks();
647 rSheet.insert( "4a: complex_in() calls (in struct; return struct)", nLoop, tEnd - tStart );
648 i = nLoop;
649 tStart = getSystemTicks();
650 while (i--)
651 xBench->complex_inout( aDummyStruct );
652 tEnd = getSystemTicks();
653 rSheet.insert( "4b: complex_inout() calls (inout struct; return struct)", nLoop, tEnd - tStart );
655 i = nLoop;
656 tStart = getSystemTicks();
657 while (i--)
658 xBench->complex_oneway( aDummyStruct );
659 tEnd = getSystemTicks();
660 rSheet.insert( "4c: complex_oneway() oneway calls (in struct)", nLoop, tEnd - tStart );
661 i = nLoop;
662 tStart = getSystemTicks();
663 while (i--)
664 xBench->complex_noreturn( aDummyStruct );
665 tEnd = getSystemTicks();
666 rSheet.insert( "4d: complex_noreturn() calls (in struct)", nLoop, tEnd - tStart );
668 // attributes, get() methods
669 i = nLoop;
670 tStart = getSystemTicks();
671 while (i--)
672 xBench->getLong();
673 tEnd = getSystemTicks();
674 rSheet.insert( "5a: getLong() call", nLoop, tEnd - tStart );
675 i = nLoop;
676 tStart = getSystemTicks();
677 while (i--)
678 xBench->getLong_attr();
679 tEnd = getSystemTicks();
680 rSheet.insert( "5b: get long attribute", nLoop, tEnd - tStart );
682 i = nLoop;
683 tStart = getSystemTicks();
684 while (i--)
685 xBench->setLong( 0 );
686 tEnd = getSystemTicks();
687 rSheet.insert( "5c: setLong() call", nLoop, tEnd - tStart );
688 i = nLoop;
689 tStart = getSystemTicks();
690 while (i--)
691 xBench->setLong_attr( 0 );
692 tEnd = getSystemTicks();
693 rSheet.insert( "5d: set long attribute", nLoop, tEnd - tStart );
695 i = nLoop;
696 tStart = getSystemTicks();
697 while (i--)
698 xBench->getHyper();
699 tEnd = getSystemTicks();
700 rSheet.insert( "5e: getHyper() call", nLoop, tEnd - tStart );
701 i = nLoop;
702 tStart = getSystemTicks();
703 while (i--)
704 xBench->getHyper_attr();
705 tEnd = getSystemTicks();
706 rSheet.insert( "5f: get hyper attribute", nLoop, tEnd - tStart );
708 i = nLoop;
709 tStart = getSystemTicks();
710 while (i--)
711 xBench->setHyper( 0 );
712 tEnd = getSystemTicks();
713 rSheet.insert( "5g: setHyper() call", nLoop, tEnd - tStart );
714 i = nLoop;
715 tStart = getSystemTicks();
716 while (i--)
717 xBench->setHyper_attr( 0 );
718 tEnd = getSystemTicks();
719 rSheet.insert( "5h: set hyper attribute", nLoop, tEnd - tStart );
721 i = nLoop;
722 tStart = getSystemTicks();
723 while (i--)
724 xBench->getFloat();
725 tEnd = getSystemTicks();
726 rSheet.insert( "5i: getFloat() call", nLoop, tEnd - tStart );
727 i = nLoop;
728 tStart = getSystemTicks();
729 while (i--)
730 xBench->getFloat_attr();
731 tEnd = getSystemTicks();
732 rSheet.insert( "5j: get float attribute",nLoop, tEnd - tStart );
734 i = nLoop;
735 tStart = getSystemTicks();
736 while (i--)
737 xBench->setFloat( 0.0 );
738 tEnd = getSystemTicks();
739 rSheet.insert( "5k: setFloat() call", nLoop, tEnd - tStart );
740 i = nLoop;
741 tStart = getSystemTicks();
742 while (i--)
743 xBench->setFloat_attr( 0.0 );
744 tEnd = getSystemTicks();
745 rSheet.insert( "5l: set float attribute", nLoop, tEnd - tStart );
747 i = nLoop;
748 tStart = getSystemTicks();
749 while (i--)
750 xBench->getDouble();
751 tEnd = getSystemTicks();
752 rSheet.insert( "5m: getDouble() call", nLoop, tEnd - tStart );
753 i = nLoop;
754 tStart = getSystemTicks();
755 while (i--)
756 xBench->getDouble_attr();
757 tEnd = getSystemTicks();
758 rSheet.insert( "5n: get double attribute", nLoop, tEnd - tStart );
759 i = nLoop;
760 tStart = getSystemTicks();
761 while (i--)
762 xBench->setDouble( 0.0 );
763 tEnd = getSystemTicks();
764 rSheet.insert( "5o: setDouble() call", nLoop, tEnd - tStart );
765 i = nLoop;
766 tStart = getSystemTicks();
767 while (i--)
768 xBench->setDouble_attr( 0.0 );
769 tEnd = getSystemTicks();
770 rSheet.insert( "5p: set double attribute", nLoop, tEnd - tStart );
772 i = nLoop;
773 tStart = getSystemTicks();
774 while (i--)
775 xBench->getString();
776 tEnd = getSystemTicks();
777 rSheet.insert( "6a: getString() call (empty)", nLoop, tEnd - tStart );
778 i = nLoop;
779 tStart = getSystemTicks();
780 while (i--)
781 xBench->getString_attr();
782 tEnd = getSystemTicks();
783 rSheet.insert( "6b: get empty string attribute", nLoop, tEnd - tStart );
785 i = nLoop;
786 OUString aDummyString;
787 tStart = getSystemTicks();
788 while (i--)
789 xBench->setString( aDummyString );
790 tEnd = getSystemTicks();
791 rSheet.insert( "6c: setString() call (emtpy)", nLoop, tEnd - tStart );
792 i = nLoop;
793 tStart = getSystemTicks();
794 while (i--)
795 xBench->setString_attr( aDummyString );
796 tEnd = getSystemTicks();
797 rSheet.insert( "6d: set empty string attribute", nLoop, tEnd - tStart );
799 i = nLoop;
800 tStart = getSystemTicks();
801 while (i--)
802 xBench->getInterface();
803 tEnd = getSystemTicks();
804 rSheet.insert( "7a: getInterface() call (null)", nLoop, tEnd - tStart );
805 i = nLoop;
806 tStart = getSystemTicks();
807 while (i--)
808 xBench->getInterface_attr();
809 tEnd = getSystemTicks();
810 rSheet.insert( "7b: get interface attribute", nLoop, tEnd - tStart );
812 i = nLoop;
813 Reference< XInterface > aDummyInterface;
814 tStart = getSystemTicks();
815 while (i--)
816 xBench->setInterface( aDummyInterface );
817 tEnd = getSystemTicks();
818 rSheet.insert( "7c: setInterface() call (null)", nLoop, tEnd - tStart );
819 i = nLoop;
820 tStart = getSystemTicks();
821 while (i--)
822 xBench->setInterface_attr( Reference< XInterface >() );
823 tEnd = getSystemTicks();
824 rSheet.insert( "7d: set interface attribute", nLoop, tEnd - tStart );
826 i = nLoop;
827 tStart = getSystemTicks();
828 while (i--)
829 xBench->getAny();
830 tEnd = getSystemTicks();
831 rSheet.insert( "8a: getAny() call (empty)", nLoop, tEnd - tStart );
832 i = nLoop;
833 tStart = getSystemTicks();
834 while (i--)
835 xBench->getAny_attr();
836 tEnd = getSystemTicks();
837 rSheet.insert( "8b: get empty any attribute", nLoop, tEnd - tStart );
839 i = nLoop;
840 Any aDummyAny;
841 tStart = getSystemTicks();
842 while (i--)
843 xBench->setAny( aDummyAny );
844 tEnd = getSystemTicks();
845 rSheet.insert( "8c: setAny() call (empty)", nLoop, tEnd - tStart );
846 i = nLoop;
847 tStart = getSystemTicks();
848 while (i--)
849 xBench->setAny_attr( aDummyAny );
850 tEnd = getSystemTicks();
851 rSheet.insert( "8d: set empty any attribute", nLoop, tEnd - tStart );
853 i = nLoop;
854 tStart = getSystemTicks();
855 while (i--)
856 xBench->getSequence();
857 tEnd = getSystemTicks();
858 rSheet.insert( "9a: getSequence() call (empty)", nLoop, tEnd - tStart );
859 i = nLoop;
860 tStart = getSystemTicks();
861 while (i--)
862 xBench->getSequence_attr();
863 tEnd = getSystemTicks();
864 rSheet.insert( "9b: get empty sequence attribute", nLoop, tEnd - tStart );
865 i = nLoop;
866 Sequence< Reference< XInterface > > aDummySeq;
867 tStart = getSystemTicks();
868 while (i--)
869 xBench->setSequence( aDummySeq );
870 tEnd = getSystemTicks();
871 rSheet.insert( "9c: setSequence() call (empty)", nLoop, tEnd - tStart );
872 i = nLoop;
873 tStart = getSystemTicks();
874 while (i--)
875 xBench->setSequence_attr( aDummySeq );
876 tEnd = getSystemTicks();
877 rSheet.insert( "9d: set empty sequence attribute", nLoop, tEnd - tStart );
879 i = nLoop;
880 tStart = getSystemTicks();
881 while (i--)
882 xBench->getStruct();
883 tEnd = getSystemTicks();
884 rSheet.insert( "Aa: getStruct() call", nLoop, tEnd - tStart );
885 i = nLoop;
886 tStart = getSystemTicks();
887 while (i--)
888 xBench->getStruct_attr();
889 tEnd = getSystemTicks();
890 rSheet.insert( "Ab: get struct attribute", nLoop, tEnd - tStart );
892 i = nLoop;
893 tStart = getSystemTicks();
894 while (i--)
895 xBench->setStruct( aDummyStruct );
896 tEnd = getSystemTicks();
897 rSheet.insert( "Ac: setStruct() call", nLoop, tEnd - tStart );
898 i = nLoop;
899 tStart = getSystemTicks();
900 while (i--)
901 xBench->setStruct_attr( aDummyStruct );
902 tEnd = getSystemTicks();
903 rSheet.insert( "Ad: set struct attribute", nLoop, tEnd - tStart );
905 // load
906 // i = nLoop;
907 // tStart = getSystemTicks();
908 // while (i--)
909 // xBench->setSequence( aSeq );
910 // tEnd = getSystemTicks();
911 // rSheet.insert( "transfer of exisiting objects", nLoop, tEnd - tStart );
913 // exceptions
914 i = nLoop;
915 tStart = getSystemTicks();
916 while (i--)
920 xBench->raiseRuntimeException();
922 catch (RuntimeException &)
926 tEnd = getSystemTicks();
927 rSheet.insert( "Ba: raising RuntimeException", nLoop, tEnd - tStart );
933 static OUString extractParam( const Sequence< OUString > & rArgs, const OUString & rParam )
935 const OUString * pArgs = rArgs.getConstArray();
936 for ( sal_Int32 nPos = rArgs.getLength(); nPos--; )
938 if (pArgs[nPos].startsWith( rParam ) &&
939 pArgs[nPos].getLength() > (rParam.getLength()+1))
941 return pArgs[nPos].copy( rParam.getLength() +1 ); // XXX=bla
944 return OUString();
947 const sal_Int32 nMagicNumberDirect = 34000;
949 //XMain
951 sal_Int32 TestImpl::run( const Sequence< OUString > & rArgs )
952 throw (RuntimeException)
954 // defaults
955 FILE * stream = stderr;
956 sal_Int64 nLoop = NLOOP;
957 OUString aArg("dms");
961 OUString aLoopStr( extractParam( rArgs, OUString("loop") ) );
962 if (aLoopStr.getLength())
964 sal_Int64 n = aLoopStr.toInt64();
965 if (n > 0)
966 nLoop = n;
969 OUString aDurationStr( extractParam( rArgs , OUString("duration" ) ) );
970 if( aDurationStr.getLength() )
972 sal_Int64 n = aDurationStr.toInt64();
973 if( n >0 )
974 nLoop = nMagicNumberDirect * n;
977 OUString aLogStr( extractParam( rArgs, OUString("log") ) );
978 if (aLogStr.getLength())
980 if (aLogStr.equalsAscii( "stderr" ) )
982 stream = stderr;
984 else if (aLogStr.equalsAscii( "stdout" ) )
986 stream = stdout;
988 else
990 OString aFileName( OUStringToOString( aLogStr, RTL_TEXTENCODING_ASCII_US ) );
991 stream = ::fopen( aFileName.getStr(), "w" );
992 if (! stream)
994 OUStringBuffer buf( 32 );
995 buf.append( "cannot open file for writing: \"" );
996 buf.append( aLogStr );
997 buf.append( "\"!" );
998 throw RuntimeException( buf.makeStringAndClear() );
1003 OUString aArgStr( extractParam( rArgs, OUString("opt") ) );
1004 if (aArgStr.getLength())
1006 aArg = aArgStr;
1009 if (! rArgs.getLength())
1010 out( "\n> no options given, using defaults" );
1012 // params
1013 out( "\n> opt=" );
1014 out( aArg );
1015 out( " log=" );
1016 if (stream == stderr)
1017 out( "stderr" );
1018 else if (stream == stdout)
1019 out( "stdout loop=" );
1020 else
1021 out( aLogStr );
1022 out( " loop=" );
1023 out( nLoop );
1024 out( "\n" );
1025 t_TimingSheetMap aSheets;
1026 TimingSheet aDirect;
1030 if (aArg.indexOf( 'd' ) >= 0)
1032 // in process direct test
1033 sal_uInt32 nStart = getSystemTicks();
1034 benchmark( aDirect, getDirect(), nLoop );
1035 sal_uInt32 nEnd = getSystemTicks();
1036 fprintf( stderr, "Duration (direct in process): %g s\n", (nEnd - nStart)/1000. );
1041 if (aArg.indexOf( 'm' ) >= 0)
1043 // in process uno dispatch
1044 Environment aCppEnv, aAnoCppEnv;
1045 OUString aCurrentLanguageBindingName( CPPU_CURRENT_LANGUAGE_BINDING_NAME );
1046 uno_getEnvironment( reinterpret_cast< uno_Environment ** >( &aCppEnv ),
1047 aCurrentLanguageBindingName.pData, 0 );
1048 // anonymous
1049 uno_createEnvironment( reinterpret_cast< uno_Environment ** >( &aAnoCppEnv ),
1050 aCurrentLanguageBindingName.pData, 0 );
1052 // pseudo mapping uno<->uno: does nothing!
1053 Mapping aMapping( aCppEnv.get(), aAnoCppEnv.get(), OUString("pseudo") );
1054 if (! aMapping.is())
1055 throw RuntimeException("no pseudo mapping available!" );
1057 Reference< XInterface > xMapped;
1058 Reference< XInterface > xDirect( getDirect() );
1059 aMapping.mapInterface( reinterpret_cast< void ** >( &xMapped ), xDirect.get(),
1060 cppu::UnoType<decltype(xDirect)>::get() );
1061 if (! xMapped.is())
1062 throw RuntimeException("mapping object failed!" );
1064 sal_uInt32 nStart = getSystemTicks();
1065 benchmark( aSheets[ "mapped in process" ], xMapped, nLoop / 100 );
1066 sal_uInt32 nEnd = getSystemTicks();
1067 fprintf( stderr, "Duration (mapped in process): %g s\n", (nStart - nEnd)/1000. );
1072 if (aArg.indexOf( 's' ) >= 0)
1074 // start server process
1075 oslSecurity hSecurity = osl_getCurrentSecurity();
1076 if (! hSecurity)
1077 throw RuntimeException("cannot get current security handle!" );
1079 OUString aArgs[] = {
1080 OUString("-c"),
1081 OUString("com.sun.star.comp.performance.PerformanceTestObject"),
1082 OUString("-l"),
1083 #ifdef SAL_UNX
1084 OUString("libperfobj.so"),
1085 #else
1086 OUString("perfobj.dll"),
1087 #endif
1088 OUString("-r"),
1089 OUString("applicat.rdb"),
1090 OUString("-u"),
1091 OUString("uno:socket,host=localhost,port=6000;iiop;TestRemoteObject"),
1092 OUString("--singleaccept")
1094 rtl_uString * pArgs[] = {
1095 aArgs[0].pData,
1096 aArgs[1].pData,
1097 aArgs[2].pData,
1098 aArgs[3].pData,
1099 aArgs[4].pData,
1100 aArgs[5].pData,
1101 aArgs[6].pData,
1102 aArgs[7].pData,
1103 aArgs[8].pData,
1106 out( "\n> executing: \"uno" );
1107 for ( sal_Int32 nPos = 0; nPos < (sizeof(aArgs) / sizeof(OUString)); ++nPos )
1109 out( " " );
1110 out( aArgs[nPos] );
1112 out( "\" ..." );
1114 oslProcess hProcess = 0;
1115 OUString aUnoExe("uno");
1116 OUString aWorkingDir(".");
1117 osl_executeProcess(
1118 aUnoExe.pData, pArgs, sizeof(aArgs) / sizeof(OUString),
1119 osl_Process_SEARCHPATH | osl_Process_DETACHED | osl_Process_NORMAL,
1120 hSecurity, aWorkingDir.pData, 0, 0, &hProcess );
1122 osl_freeSecurityHandle( hSecurity );
1123 if (! hProcess)
1124 throw RuntimeException("cannot start server process!" );
1125 osl_freeProcessHandle( hProcess );
1127 // wait three seconds
1128 TimeValue threeSeconds;
1129 threeSeconds.Seconds = 3;
1130 osl_waitThread( &threeSeconds );
1132 // connect and resolve outer process object
1133 Reference< XInterface > xResolvedObject( resolveObject( OUString("uno:socket,host=localhost,port=6000;iiop;TestRemoteObject") ) );
1135 benchmark( aSheets[ "remote same host" ], xResolvedObject, nLoop / 300 );
1140 if (aArg.indexOf( 'r' ) >= 0)
1142 // remote
1143 OUString aUnoUrl( extractParam( rArgs, OUString("url") ) );
1144 if (! aUnoUrl.getLength())
1145 throw RuntimeException( "performance test r(emote) needs additional uno url!" );
1147 // connect and resolve outer process object
1148 Reference< XInterface > xResolvedObject( resolveObject( aUnoUrl ) );
1150 sal_Int32 t1 = getSystemTicks();
1151 OString o = OUStringToOString( aUnoUrl, RTL_TEXTENCODING_ASCII_US );
1152 benchmark( aSheets[ o.getStr() ], xResolvedObject, nLoop / 900 );
1153 sal_Int32 t2 = getSystemTicks();
1154 fprintf( stderr, "Duration (%s): %g s\n", o.getStr(),(t2 - t1)/1000. );
1159 if (aArg.indexOf( 'j' ) >= 0)
1161 // java
1162 benchmark( aSheets[ "java in process" ],
1163 _xSMgr->createInstance("com.sun.star.comp.benchmark.JavaTestObject"),
1164 nLoop / 1000 );
1168 // dump out tables
1170 out( "\nTimes( ratio to direct in process )", stream );
1171 #if OSL_DEBUG_LEVEL > 1
1172 out ("; compiled with OSL_DEBUG_LEVEL > 1", stream );
1173 #endif
1174 out( ":", stream );
1176 sal_Int32 nPos = 60;
1177 out( "[direct in process]", stream, nPos );
1178 t_TimingSheetMap::const_iterator iSheets( aSheets.begin() );
1179 for ( ; iSheets != aSheets.end(); ++iSheets )
1181 nPos += 40;
1182 out( "[", stream, nPos );
1183 out( (*iSheets).first.c_str(), stream );
1184 out( "]", stream );
1186 for ( t_TimeEntryMap::const_iterator iTopics( aDirect._entries.begin() );
1187 iTopics != aDirect._entries.end(); ++iTopics )
1189 const std::string & rTopic = (*iTopics).first;
1191 out( "\n", stream );
1192 out( rTopic.c_str(), stream );
1194 out( ":", stream, 58, '.' );
1196 sal_Int32 nPos = 60;
1198 double secs = (*iTopics).second.secPerCall();
1199 if (secs > 0.0)
1201 out( secs * 1000, stream, nPos );
1202 out( "ms", stream );
1204 else
1206 out( "NA", stream, nPos );
1209 iSheets = aSheets.begin();
1210 for ( ; iSheets != aSheets.end(); ++iSheets )
1212 const t_TimeEntryMap::const_iterator iFind( (*iSheets).second._entries.find( rTopic ) );
1213 OSL_ENSURE( iFind != (*iSheets).second._entries.end(), "####" );
1215 nPos += 40;
1217 double secs = (*iFind).second.secPerCall();
1218 if (secs != 0.0)
1220 out( secs * 1000, stream, nPos );
1221 out( "ms", stream );
1223 out( " (", stream );
1224 double ratio = (*iFind).second.ratio( (*iTopics).second );
1225 if (ratio != 0.0)
1227 out( ratio, stream );
1228 out( " x)", stream );
1230 else
1232 out( "NA)", stream );
1235 else
1237 out( "NA", stream, nPos );
1242 catch (Exception & rExc)
1244 if (stream != stderr && stream != stdout)
1245 ::fclose( stream );
1246 throw RuntimeException( rExc.Message, rExc.Context );
1249 if (stream != stderr && stream != stdout)
1250 ::fclose( stream );
1252 out( "\n> done.\n" );
1253 return 0;
1264 extern "C"
1267 sal_Bool SAL_CALL component_writeInfo(
1268 void * pServiceManager, void * pRegistryKey )
1270 if (pRegistryKey)
1274 Reference< XRegistryKey > xNewKey(
1275 reinterpret_cast< XRegistryKey * >( pRegistryKey )->createKey(
1276 OUString( "/" IMPLNAME "/UNO/SERVICES" ) ) );
1277 xNewKey->createKey( OUString( SERVICENAME ) );
1279 return sal_True;
1281 catch (InvalidRegistryException &)
1283 OSL_FAIL( "### InvalidRegistryException!" );
1286 return sal_False;
1289 SAL_DLLPUBLIC_EXPORT void * SAL_CALL component_getFactory(
1290 const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey )
1292 void * pRet = 0;
1294 if (pServiceManager && rtl_str_compare( pImplName, IMPLNAME ) == 0)
1296 Reference< XSingleServiceFactory > xFactory( createSingleFactory(
1297 reinterpret_cast< XMultiServiceFactory * >( pServiceManager ),
1298 OUString( IMPLNAME ),
1299 benchmark_test::TestImpl_create,
1300 benchmark_test::getSupportedServiceNames() ) );
1302 if (xFactory.is())
1304 xFactory->acquire();
1305 pRet = xFactory.get();
1309 return pRet;
1313 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */