Version 7.5.1.1, tag libreoffice-7.5.1.1
[LibreOffice.git] / testtools / source / performance / ubtest.cxx
blob17601820c9662f1d0a2e54e17edb1be71ae5f5ef
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.hxx>
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 char * pText, FILE * stream = stderr,
115 sal_Int32 nStart = -1, char cFillchar = ' ' )
117 static sal_Int32 s_nPos = 0;
119 char ar[2] = { cFillchar, 0 };
120 while (s_nPos < nStart)
122 ::fprintf( stream, ar );
123 ++s_nPos;
126 ::fprintf( stream, pText );
128 for ( const 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, 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, char cFillchar = ' ' )
147 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, char cFillchar = ' ' )
155 char ar[128];
156 ::snprintf( ar, sizeof(ar), "%" SAL_PRIdINT64, 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 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("connector"),
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 return { SERVICENAME };
395 class TestImpl : public WeakImplHelper< XServiceInfo, XMain >
397 Reference< XMultiServiceFactory > _xSMgr;
399 Reference< XInterface > _xDirect;
400 Reference< XInterface > getDirect() throw (Exception);
401 Reference< XInterface > resolveObject( const OUString & rUnoUrl ) throw (Exception);
403 public:
404 explicit TestImpl( const Reference< XMultiServiceFactory > & xSMgr );
405 virtual ~TestImpl();
407 // XServiceInfo
408 virtual OUString SAL_CALL getImplementationName() throw (RuntimeException);
409 virtual sal_Bool SAL_CALL supportsService( const OUString & rServiceName ) throw (RuntimeException);
410 virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() throw (RuntimeException);
412 // XMain
413 virtual sal_Int32 SAL_CALL run( const Sequence< OUString > & rArgs ) throw (RuntimeException);
417 TestImpl::TestImpl( const Reference< XMultiServiceFactory > & xSMgr )
418 : _xSMgr( xSMgr )
422 TestImpl::~TestImpl()
427 static Reference< XInterface > SAL_CALL TestImpl_create( const Reference< XMultiServiceFactory > & xSMgr )
429 return Reference< XInterface >( *new TestImpl( xSMgr ) );
432 // XServiceInfo
434 OUString TestImpl::getImplementationName()
435 throw (RuntimeException)
437 return OUString( IMPLNAME );
440 sal_Bool TestImpl::supportsService( const OUString & rServiceName )
441 throw (RuntimeException)
443 return cppu::supportsService(this, rServiceName);
446 Sequence< OUString > TestImpl::getSupportedServiceNames()
447 throw (RuntimeException)
449 return benchmark_test::getSupportedServiceNames();
453 Reference< XInterface > TestImpl::getDirect()
454 throw (Exception)
456 if (! _xDirect.is())
458 MutexGuard aGuard( Mutex::getGlobalMutex() );
459 if (! _xDirect.is())
461 Reference< XSingleServiceFactory > xFac( loadLibComponentFactory(
462 OUString("perfobj"),
463 OUString("com.sun.star.comp.performance.PerformanceTestObject"),
464 _xSMgr, Reference< XRegistryKey >() ) );
465 if (! xFac.is())
466 throw RuntimeException("no test object available!" );
467 _xDirect = xFac->createInstance();
470 return _xDirect;
473 Reference< XInterface > TestImpl::resolveObject( const OUString & rUnoUrl )
474 throw (Exception)
476 Reference< XUnoUrlResolver > xResolver;
477 createInstance(
478 xResolver, _xSMgr,
479 OUString("com.sun.star.bridge.UnoUrlResolver") );
481 Reference< XInterface > xResolvedObject( xResolver->resolve( rUnoUrl ) );
483 if (! xResolvedObject.is())
485 throw RuntimeException( "cannot resolve object \"" + rUnoUrl + "\"!" );
488 return xResolvedObject;
492 class TimeEntry
494 sal_Int64 nLoop;
495 sal_uInt32 nTicks;
497 public:
498 TimeEntry()
500 TimeEntry( sal_Int64 nLoop_, sal_uInt32 nTicks_ )
501 : nLoop( nLoop_ )
502 , nTicks( nTicks_ )
505 inline double secPerCall() const
506 { return (((double)nTicks) / (nLoop * 1000)); }
508 double ratio( const TimeEntry & rEntry ) const;
511 double TimeEntry::ratio( const TimeEntry & rEntry ) const
513 double f = rEntry.nTicks * nLoop;
514 if (f == 0.0)
516 return 0.0;
518 else
520 return (((double)(nTicks * rEntry.nLoop)) / f);
525 typedef std::map< std::string, TimeEntry > t_TimeEntryMap;
528 struct TimingSheet
530 t_TimeEntryMap _entries;
531 void insert( const char * pText, sal_Int64 nLoop, sal_uInt32 nTicks );
534 void TimingSheet::insert( const char * pText, sal_Int64 nLoop, sal_uInt32 nTicks )
536 _entries[ pText ] = TimeEntry( nLoop, nTicks );
539 typedef std::unordered_map< std::string, TimingSheet > t_TimingSheetMap;
541 static void benchmark(
542 TimingSheet & rSheet, const Reference< XInterface > & xInstance, sal_Int64 nLoop )
543 throw (Exception)
545 Reference< XPerformanceTest > xBench( xInstance, UNO_QUERY_THROW );
547 sal_Int64 i;
548 sal_uInt32 tStart, tEnd;
550 const Type & rKnownType = cppu::UnoType<XPerformanceTest>::get();
551 const Type & rUnKnownType = cppu::UnoType<XSet>::get();
553 ComplexTypes aDummyStruct;
556 // oneway calls
557 i = nLoop;
558 tStart = getSystemTicks();
559 while (i--)
560 xBench->async();
561 sal_uInt32 tEndSend = getSystemTicks();
562 xBench->sync();
563 tEnd = getSystemTicks();
564 rSheet.insert( "1a: sending simple oneway calls (no params, no return)", nLoop, tEndSend - tStart );
565 rSheet.insert( "1b: simple oneway calls (no params, no return)", nLoop, tEnd - tStart );
566 // synchron calls
567 i = nLoop;
568 tStart = getSystemTicks();
569 while (i--)
570 xBench->sync();
571 xBench->sync();
572 tEnd = getSystemTicks();
573 rSheet.insert( "1c: simple synchron calls (no params no return)", nLoop+1, tEnd - tStart );
575 // acquire
576 i = nLoop;
577 tStart = getSystemTicks();
578 while (i--)
579 xBench->acquire();
580 tEnd = getSystemTicks();
581 rSheet.insert( "2a: interface acquire() calls", nLoop, tEnd - tStart );
582 // release
583 i = nLoop;
584 tStart = getSystemTicks();
585 while (i--)
586 xBench->release();
587 tEnd = getSystemTicks();
588 rSheet.insert( "2b: interface release() calls", nLoop, tEnd - tStart );
590 // queryInterface() for known type
591 i = nLoop;
592 tStart = getSystemTicks();
593 while (i--)
594 xBench->queryInterface( rKnownType );
595 tEnd = getSystemTicks();
596 rSheet.insert( "2c: interface query for implemented type", nLoop, tEnd - tStart );
597 // queryInterface() for unknown type
598 i = nLoop;
599 tStart = getSystemTicks();
600 while (i--)
601 xBench->queryInterface( rUnKnownType );
602 tEnd = getSystemTicks();
603 rSheet.insert( "2d: interface query for unknown type", nLoop, tEnd - tStart );
605 // create and forget objects
606 Reference< XPerformanceTest > xBench2( xBench );
607 i = nLoop;
608 tStart = getSystemTicks();
609 while (i--)
610 xBench2 = xBench2->createObject();
611 tEnd = getSystemTicks();
612 rSheet.insert( "3a: create and release test objects", nLoop, tEnd - tStart );
614 // hold new objects
615 Sequence< Reference< XInterface > > aSeq( nLoop / 100 );
616 Reference< XInterface > * pSeq = aSeq.getArray();
617 xBench2 = xBench;
618 i = aSeq.getLength();
619 tStart = getSystemTicks();
620 while (i--)
621 pSeq[i] = xBench2 = xBench2->createObject();
622 tEnd = getSystemTicks();
623 rSheet.insert( "3b: create and hold test objects", nLoop, tEnd - tStart );
625 // structs
626 i = nLoop;
627 tStart = getSystemTicks();
628 while (i--)
629 xBench->complexIn( aDummyStruct );
630 tEnd = getSystemTicks();
631 rSheet.insert( "4a: complexIn() calls (in struct; return struct)", nLoop, tEnd - tStart );
632 i = nLoop;
633 tStart = getSystemTicks();
634 while (i--)
635 xBench->complexInout( aDummyStruct );
636 tEnd = getSystemTicks();
637 rSheet.insert( "4b: complexInout() calls (inout struct; return struct)", nLoop, tEnd - tStart );
639 i = nLoop;
640 tStart = getSystemTicks();
641 while (i--)
642 xBench->complexOneway( aDummyStruct );
643 tEnd = getSystemTicks();
644 rSheet.insert( "4c: complexOneway() oneway calls (in struct)", nLoop, tEnd - tStart );
645 i = nLoop;
646 tStart = getSystemTicks();
647 while (i--)
648 xBench->complexNoreturn( aDummyStruct );
649 tEnd = getSystemTicks();
650 rSheet.insert( "4d: complexNoreturn() calls (in struct)", nLoop, tEnd - tStart );
652 // attributes, get() methods
653 i = nLoop;
654 tStart = getSystemTicks();
655 while (i--)
656 xBench->getLong();
657 tEnd = getSystemTicks();
658 rSheet.insert( "5a: getLong() call", nLoop, tEnd - tStart );
659 i = nLoop;
660 tStart = getSystemTicks();
661 while (i--)
662 xBench->getLong_attr();
663 tEnd = getSystemTicks();
664 rSheet.insert( "5b: get long attribute", nLoop, tEnd - tStart );
666 i = nLoop;
667 tStart = getSystemTicks();
668 while (i--)
669 xBench->setLong( 0 );
670 tEnd = getSystemTicks();
671 rSheet.insert( "5c: setLong() call", nLoop, tEnd - tStart );
672 i = nLoop;
673 tStart = getSystemTicks();
674 while (i--)
675 xBench->setLong_attr( 0 );
676 tEnd = getSystemTicks();
677 rSheet.insert( "5d: set long attribute", nLoop, tEnd - tStart );
679 i = nLoop;
680 tStart = getSystemTicks();
681 while (i--)
682 xBench->getHyper();
683 tEnd = getSystemTicks();
684 rSheet.insert( "5e: getHyper() call", nLoop, tEnd - tStart );
685 i = nLoop;
686 tStart = getSystemTicks();
687 while (i--)
688 xBench->getHyper_attr();
689 tEnd = getSystemTicks();
690 rSheet.insert( "5f: get hyper attribute", nLoop, tEnd - tStart );
692 i = nLoop;
693 tStart = getSystemTicks();
694 while (i--)
695 xBench->setHyper( 0 );
696 tEnd = getSystemTicks();
697 rSheet.insert( "5g: setHyper() call", nLoop, tEnd - tStart );
698 i = nLoop;
699 tStart = getSystemTicks();
700 while (i--)
701 xBench->setHyper_attr( 0 );
702 tEnd = getSystemTicks();
703 rSheet.insert( "5h: set hyper attribute", nLoop, tEnd - tStart );
705 i = nLoop;
706 tStart = getSystemTicks();
707 while (i--)
708 xBench->getFloat();
709 tEnd = getSystemTicks();
710 rSheet.insert( "5i: getFloat() call", nLoop, tEnd - tStart );
711 i = nLoop;
712 tStart = getSystemTicks();
713 while (i--)
714 xBench->getFloat_attr();
715 tEnd = getSystemTicks();
716 rSheet.insert( "5j: get float attribute",nLoop, tEnd - tStart );
718 i = nLoop;
719 tStart = getSystemTicks();
720 while (i--)
721 xBench->setFloat( 0.0 );
722 tEnd = getSystemTicks();
723 rSheet.insert( "5k: setFloat() call", nLoop, tEnd - tStart );
724 i = nLoop;
725 tStart = getSystemTicks();
726 while (i--)
727 xBench->setFloat_attr( 0.0 );
728 tEnd = getSystemTicks();
729 rSheet.insert( "5l: set float attribute", nLoop, tEnd - tStart );
731 i = nLoop;
732 tStart = getSystemTicks();
733 while (i--)
734 xBench->getDouble();
735 tEnd = getSystemTicks();
736 rSheet.insert( "5m: getDouble() call", nLoop, tEnd - tStart );
737 i = nLoop;
738 tStart = getSystemTicks();
739 while (i--)
740 xBench->getDouble_attr();
741 tEnd = getSystemTicks();
742 rSheet.insert( "5n: get double attribute", nLoop, tEnd - tStart );
743 i = nLoop;
744 tStart = getSystemTicks();
745 while (i--)
746 xBench->setDouble( 0.0 );
747 tEnd = getSystemTicks();
748 rSheet.insert( "5o: setDouble() call", nLoop, tEnd - tStart );
749 i = nLoop;
750 tStart = getSystemTicks();
751 while (i--)
752 xBench->setDouble_attr( 0.0 );
753 tEnd = getSystemTicks();
754 rSheet.insert( "5p: set double attribute", nLoop, tEnd - tStart );
756 i = nLoop;
757 tStart = getSystemTicks();
758 while (i--)
759 xBench->getString();
760 tEnd = getSystemTicks();
761 rSheet.insert( "6a: getString() call (empty)", nLoop, tEnd - tStart );
762 i = nLoop;
763 tStart = getSystemTicks();
764 while (i--)
765 xBench->getString_attr();
766 tEnd = getSystemTicks();
767 rSheet.insert( "6b: get empty string attribute", nLoop, tEnd - tStart );
769 i = nLoop;
770 OUString aDummyString;
771 tStart = getSystemTicks();
772 while (i--)
773 xBench->setString( aDummyString );
774 tEnd = getSystemTicks();
775 rSheet.insert( "6c: setString() call (empty)", nLoop, tEnd - tStart );
776 i = nLoop;
777 tStart = getSystemTicks();
778 while (i--)
779 xBench->setString_attr( aDummyString );
780 tEnd = getSystemTicks();
781 rSheet.insert( "6d: set empty string attribute", nLoop, tEnd - tStart );
783 i = nLoop;
784 tStart = getSystemTicks();
785 while (i--)
786 xBench->getInterface();
787 tEnd = getSystemTicks();
788 rSheet.insert( "7a: getInterface() call (null)", nLoop, tEnd - tStart );
789 i = nLoop;
790 tStart = getSystemTicks();
791 while (i--)
792 xBench->getInterface_attr();
793 tEnd = getSystemTicks();
794 rSheet.insert( "7b: get interface attribute", nLoop, tEnd - tStart );
796 i = nLoop;
797 Reference< XInterface > aDummyInterface;
798 tStart = getSystemTicks();
799 while (i--)
800 xBench->setInterface( aDummyInterface );
801 tEnd = getSystemTicks();
802 rSheet.insert( "7c: setInterface() call (null)", nLoop, tEnd - tStart );
803 i = nLoop;
804 tStart = getSystemTicks();
805 while (i--)
806 xBench->setInterface_attr( Reference< XInterface >() );
807 tEnd = getSystemTicks();
808 rSheet.insert( "7d: set interface attribute", nLoop, tEnd - tStart );
810 i = nLoop;
811 tStart = getSystemTicks();
812 while (i--)
813 xBench->getAny();
814 tEnd = getSystemTicks();
815 rSheet.insert( "8a: getAny() call (empty)", nLoop, tEnd - tStart );
816 i = nLoop;
817 tStart = getSystemTicks();
818 while (i--)
819 xBench->getAny_attr();
820 tEnd = getSystemTicks();
821 rSheet.insert( "8b: get empty any attribute", nLoop, tEnd - tStart );
823 i = nLoop;
824 Any aDummyAny;
825 tStart = getSystemTicks();
826 while (i--)
827 xBench->setAny( aDummyAny );
828 tEnd = getSystemTicks();
829 rSheet.insert( "8c: setAny() call (empty)", nLoop, tEnd - tStart );
830 i = nLoop;
831 tStart = getSystemTicks();
832 while (i--)
833 xBench->setAny_attr( aDummyAny );
834 tEnd = getSystemTicks();
835 rSheet.insert( "8d: set empty any attribute", nLoop, tEnd - tStart );
837 i = nLoop;
838 tStart = getSystemTicks();
839 while (i--)
840 xBench->getSequence();
841 tEnd = getSystemTicks();
842 rSheet.insert( "9a: getSequence() call (empty)", nLoop, tEnd - tStart );
843 i = nLoop;
844 tStart = getSystemTicks();
845 while (i--)
846 xBench->getSequence_attr();
847 tEnd = getSystemTicks();
848 rSheet.insert( "9b: get empty sequence attribute", nLoop, tEnd - tStart );
849 i = nLoop;
850 Sequence< Reference< XInterface > > aDummySeq;
851 tStart = getSystemTicks();
852 while (i--)
853 xBench->setSequence( aDummySeq );
854 tEnd = getSystemTicks();
855 rSheet.insert( "9c: setSequence() call (empty)", nLoop, tEnd - tStart );
856 i = nLoop;
857 tStart = getSystemTicks();
858 while (i--)
859 xBench->setSequence_attr( aDummySeq );
860 tEnd = getSystemTicks();
861 rSheet.insert( "9d: set empty sequence attribute", nLoop, tEnd - tStart );
863 i = nLoop;
864 tStart = getSystemTicks();
865 while (i--)
866 xBench->getStruct();
867 tEnd = getSystemTicks();
868 rSheet.insert( "Aa: getStruct() call", nLoop, tEnd - tStart );
869 i = nLoop;
870 tStart = getSystemTicks();
871 while (i--)
872 xBench->getStruct_attr();
873 tEnd = getSystemTicks();
874 rSheet.insert( "Ab: get struct attribute", nLoop, tEnd - tStart );
876 i = nLoop;
877 tStart = getSystemTicks();
878 while (i--)
879 xBench->setStruct( aDummyStruct );
880 tEnd = getSystemTicks();
881 rSheet.insert( "Ac: setStruct() call", nLoop, tEnd - tStart );
882 i = nLoop;
883 tStart = getSystemTicks();
884 while (i--)
885 xBench->setStruct_attr( aDummyStruct );
886 tEnd = getSystemTicks();
887 rSheet.insert( "Ad: set struct attribute", nLoop, tEnd - tStart );
889 // load
890 // i = nLoop;
891 // tStart = getSystemTicks();
892 // while (i--)
893 // xBench->setSequence( aSeq );
894 // tEnd = getSystemTicks();
895 // rSheet.insert( "transfer of existing objects", nLoop, tEnd - tStart );
897 // exceptions
898 i = nLoop;
899 tStart = getSystemTicks();
900 while (i--)
904 xBench->raiseRuntimeException();
906 catch (RuntimeException &)
910 tEnd = getSystemTicks();
911 rSheet.insert( "Ba: raising RuntimeException", nLoop, tEnd - tStart );
917 static OUString extractParam( const Sequence< OUString > & rArgs, const OUString & rParam )
919 const OUString * pArgs = rArgs.getConstArray();
920 for ( sal_Int32 nPos = rArgs.getLength(); nPos--; )
922 if (pArgs[nPos].startsWith( rParam ) &&
923 pArgs[nPos].getLength() > (rParam.getLength()+1))
925 return pArgs[nPos].copy( rParam.getLength() +1 ); // XXX=bla
928 return OUString();
931 const sal_Int32 nMagicNumberDirect = 34000;
933 //XMain
935 sal_Int32 TestImpl::run( const Sequence< OUString > & rArgs )
936 throw (RuntimeException)
938 // defaults
939 FILE * stream = stderr;
940 sal_Int64 nLoop = NLOOP;
941 OUString aArg("dms");
945 OUString aLoopStr( extractParam( rArgs, OUString("loop") ) );
946 if (aLoopStr.getLength())
948 sal_Int64 n = aLoopStr.toInt64();
949 if (n > 0)
950 nLoop = n;
953 OUString aDurationStr( extractParam( rArgs , OUString("duration" ) ) );
954 if( aDurationStr.getLength() )
956 sal_Int64 n = aDurationStr.toInt64();
957 if( n >0 )
958 nLoop = nMagicNumberDirect * n;
961 OUString aLogStr( extractParam( rArgs, OUString("log") ) );
962 if (aLogStr.getLength())
964 if (aLogStr.equalsAscii( "stderr" ) )
966 stream = stderr;
968 else if (aLogStr.equalsAscii( "stdout" ) )
970 stream = stdout;
972 else
974 OString aFileName( OUStringToOString( aLogStr, RTL_TEXTENCODING_ASCII_US ) );
975 stream = ::fopen( aFileName.getStr(), "w" );
976 if (! stream)
978 throw RuntimeException( "cannot open file for writing: \"" + aLogStr + "\"!" );
983 OUString aArgStr( extractParam( rArgs, OUString("opt") ) );
984 if (aArgStr.getLength())
986 aArg = aArgStr;
989 if (! rArgs.getLength())
990 out( "\n> no options given, using defaults" );
992 // params
993 out( "\n> opt=" );
994 out( aArg );
995 out( " log=" );
996 if (stream == stderr)
997 out( "stderr" );
998 else if (stream == stdout)
999 out( "stdout loop=" );
1000 else
1001 out( aLogStr );
1002 out( " loop=" );
1003 out( nLoop );
1004 out( "\n" );
1005 t_TimingSheetMap aSheets;
1006 TimingSheet aDirect;
1009 if (aArg.indexOf( 'd' ) >= 0)
1011 // in process direct test
1012 sal_uInt32 nStart = getSystemTicks();
1013 benchmark( aDirect, getDirect(), nLoop );
1014 sal_uInt32 nEnd = getSystemTicks();
1015 fprintf( stderr, "Duration (direct in process): %g s\n", (nEnd - nStart)/1000. );
1019 if (aArg.indexOf( 'm' ) >= 0)
1021 // in process uno dispatch
1022 Environment aCppEnv, aAnoCppEnv;
1023 OUString aCurrentLanguageBindingName( CPPU_CURRENT_LANGUAGE_BINDING_NAME );
1024 uno_getEnvironment( reinterpret_cast< uno_Environment ** >( &aCppEnv ),
1025 aCurrentLanguageBindingName.pData, 0 );
1026 // anonymous
1027 uno_createEnvironment( reinterpret_cast< uno_Environment ** >( &aAnoCppEnv ),
1028 aCurrentLanguageBindingName.pData, 0 );
1030 // pseudo mapping uno<->uno: does nothing!
1031 Mapping aMapping( aCppEnv.get(), aAnoCppEnv.get(), OUString("pseudo") );
1032 if (! aMapping.is())
1033 throw RuntimeException("no pseudo mapping available!" );
1035 Reference< XInterface > xMapped;
1036 Reference< XInterface > xDirect( getDirect() );
1037 aMapping.mapInterface( reinterpret_cast< void ** >( &xMapped ), xDirect.get(),
1038 cppu::UnoType<decltype(xDirect)>::get() );
1039 if (! xMapped.is())
1040 throw RuntimeException("mapping object failed!" );
1042 sal_uInt32 nStart = getSystemTicks();
1043 benchmark( aSheets[ "mapped in process" ], xMapped, nLoop / 100 );
1044 sal_uInt32 nEnd = getSystemTicks();
1045 fprintf( stderr, "Duration (mapped in process): %g s\n", (nStart - nEnd)/1000. );
1049 if (aArg.indexOf( 's' ) >= 0)
1051 // start server process
1052 oslSecurity hSecurity = osl_getCurrentSecurity();
1053 if (! hSecurity)
1054 throw RuntimeException("cannot get current security handle!" );
1056 OUString aArgs[] = {
1057 OUString("-c"),
1058 OUString("com.sun.star.comp.performance.PerformanceTestObject"),
1059 OUString("-l"),
1060 #ifdef SAL_UNX
1061 OUString("libperfobj.so"),
1062 #else
1063 OUString("perfobj.dll"),
1064 #endif
1065 OUString("-r"),
1066 OUString("applicat.rdb"),
1067 OUString("-u"),
1068 OUString("uno:socket,host=localhost,port=6000;iiop;TestRemoteObject"),
1069 OUString("--singleaccept")
1071 rtl_uString * pArgs[] = {
1072 aArgs[0].pData,
1073 aArgs[1].pData,
1074 aArgs[2].pData,
1075 aArgs[3].pData,
1076 aArgs[4].pData,
1077 aArgs[5].pData,
1078 aArgs[6].pData,
1079 aArgs[7].pData,
1080 aArgs[8].pData,
1083 out( "\n> executing: \"uno" );
1084 for ( sal_Int32 nPos = 0; nPos < (sizeof(aArgs) / sizeof(OUString)); ++nPos )
1086 out( " " );
1087 out( aArgs[nPos] );
1089 out( "\" ..." );
1091 oslProcess hProcess = 0;
1092 OUString aUnoExe("uno");
1093 OUString aWorkingDir(".");
1094 osl_executeProcess(
1095 aUnoExe.pData, pArgs, sizeof(aArgs) / sizeof(OUString),
1096 osl_Process_SEARCHPATH | osl_Process_DETACHED | osl_Process_NORMAL,
1097 hSecurity, aWorkingDir.pData, 0, 0, &hProcess );
1099 osl_freeSecurityHandle( hSecurity );
1100 if (! hProcess)
1101 throw RuntimeException("cannot start server process!" );
1102 osl_freeProcessHandle( hProcess );
1104 // wait three seconds
1105 osl::Thread::wait(std::chrono::seconds(3));
1107 // connect and resolve outer process object
1108 Reference< XInterface > xResolvedObject( resolveObject( OUString("uno:socket,host=localhost,port=6000;iiop;TestRemoteObject") ) );
1110 benchmark( aSheets[ "remote same host" ], xResolvedObject, nLoop / 300 );
1114 if (aArg.indexOf( 'r' ) >= 0)
1116 // remote
1117 OUString aUnoUrl( extractParam( rArgs, OUString("url") ) );
1118 if (! aUnoUrl.getLength())
1119 throw RuntimeException( "performance test r(emote) needs additional uno url!" );
1121 // connect and resolve outer process object
1122 Reference< XInterface > xResolvedObject( resolveObject( aUnoUrl ) );
1124 sal_Int32 t1 = getSystemTicks();
1125 OString o = OUStringToOString( aUnoUrl, RTL_TEXTENCODING_ASCII_US );
1126 benchmark( aSheets[ o.getStr() ], xResolvedObject, nLoop / 900 );
1127 sal_Int32 t2 = getSystemTicks();
1128 fprintf( stderr, "Duration (%s): %g s\n", o.getStr(),(t2 - t1)/1000. );
1132 if (aArg.indexOf( 'j' ) >= 0)
1134 // java
1135 benchmark( aSheets[ "java in process" ],
1136 _xSMgr->createInstance("com.sun.star.comp.benchmark.JavaTestObject"),
1137 nLoop / 1000 );
1141 // dump out tables
1143 out( "\nTimes( ratio to direct in process )", stream );
1144 out( ":", stream );
1146 sal_Int32 nPos = 60;
1147 out( "[direct in process]", stream, nPos );
1148 for ( const auto& rSheet : aSheets )
1150 nPos += 40;
1151 out( "[", stream, nPos );
1152 out( rSheet.first.c_str(), stream );
1153 out( "]", stream );
1155 for ( const auto& rTopics : aDirect._entries )
1157 const std::string & rTopic = rTopics.first;
1159 out( "\n", stream );
1160 out( rTopic.c_str(), stream );
1162 out( ":", stream, 58, '.' );
1164 sal_Int32 nPos = 60;
1166 double secs = rTopics.second.secPerCall();
1167 if (secs > 0.0)
1169 out( secs * 1000, stream, nPos );
1170 out( "ms", stream );
1172 else
1174 out( "NA", stream, nPos );
1177 for ( const auto& rSheet : aSheets )
1179 const t_TimeEntryMap::const_iterator iFind( rSheet.second._entries.find( rTopic ) );
1180 OSL_ENSURE( iFind != rSheet.second._entries.end(), "####" );
1182 nPos += 40;
1184 double secs = (*iFind).second.secPerCall();
1185 if (secs != 0.0)
1187 out( secs * 1000, stream, nPos );
1188 out( "ms", stream );
1190 out( " (", stream );
1191 double ratio = (*iFind).second.ratio( rTopics.second );
1192 if (ratio != 0.0)
1194 out( ratio, stream );
1195 out( " x)", stream );
1197 else
1199 out( "NA)", stream );
1202 else
1204 out( "NA", stream, nPos );
1209 catch (Exception & rExc)
1211 if (stream != stderr && stream != stdout)
1212 ::fclose( stream );
1213 throw RuntimeException( rExc.Message, rExc.Context );
1216 if (stream != stderr && stream != stdout)
1217 ::fclose( stream );
1219 out( "\n> done.\n" );
1220 return 0;
1226 extern "C"
1229 sal_Bool SAL_CALL component_writeInfo(
1230 void * pServiceManager, void * pRegistryKey )
1232 if (pRegistryKey)
1236 Reference< XRegistryKey > xNewKey(
1237 reinterpret_cast< XRegistryKey * >( pRegistryKey )->createKey(
1238 OUString( "/" IMPLNAME "/UNO/SERVICES" ) ) );
1239 xNewKey->createKey( OUString( SERVICENAME ) );
1241 return sal_True;
1243 catch (InvalidRegistryException &)
1245 OSL_FAIL( "### InvalidRegistryException!" );
1248 return sal_False;
1251 SAL_DLLPUBLIC_EXPORT void * SAL_CALL component_getFactory(
1252 const char * pImplName, void * pServiceManager, void * pRegistryKey )
1254 void * pRet = 0;
1256 if (pServiceManager && rtl_str_compare( pImplName, IMPLNAME ) == 0)
1258 Reference< XSingleServiceFactory > xFactory( createSingleFactory(
1259 reinterpret_cast< XMultiServiceFactory * >( pServiceManager ),
1260 OUString( IMPLNAME ),
1261 benchmark_test::TestImpl_create,
1262 benchmark_test::getSupportedServiceNames() ) );
1264 if (xFactory.is())
1266 xFactory->acquire();
1267 pRet = xFactory.get();
1271 return pRet;
1275 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */