1 /**************************************************************
2  *
3  * Licensed to the Apache Software Foundation (ASF) under one
4  * or more contributor license agreements.  See the NOTICE file
5  * distributed with this work for additional information
6  * regarding copyright ownership.  The ASF licenses this file
7  * to you under the Apache License, Version 2.0 (the
8  * "License"); you may not use this file except in compliance
9  * with the License.  You may obtain a copy of the License at
10  *
11  *   http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing,
14  * software distributed under the License is distributed on an
15  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16  * KIND, either express or implied.  See the License for the
17  * specific language governing permissions and limitations
18  * under the License.
19  *
20  *************************************************************/
21 
22 
23 
24 // MARKER(update_precomp.py): autogen include statement, do not remove
25 #include "precompiled_testtools.hxx"
26 
27 #include <stdio.h>
28 #include <math.h>
29 #include <string>
30 #include <hash_map>
31 #include <map>
32 
33 #include <osl/diagnose.h>
34 #include <osl/mutex.hxx>
35 #include <osl/module.h>
36 #include <osl/process.h>
37 #include <osl/thread.h>
38 #include <osl/conditn.hxx>
39 #include <osl/time.h>
40 
41 #ifdef SAL_W32
42 #include <windows.h>
43 #else
44 #include <sys/times.h>
45 #include <unistd.h>
46 #endif
47 
48 #include <rtl/string.hxx>
49 #include <rtl/strbuf.hxx>
50 #include <rtl/ustrbuf.hxx>
51 
52 #include <uno/environment.hxx>
53 #include <uno/mapping.hxx>
54 
55 #include <cppuhelper/factory.hxx>
56 #include <cppuhelper/implbase2.hxx>
57 
58 #include <com/sun/star/lang/XServiceInfo.hpp>
59 #include <com/sun/star/lang/XComponent.hpp>
60 #include <com/sun/star/lang/XMain.hpp>
61 #include <com/sun/star/lang/XInitialization.hpp>
62 #include <com/sun/star/loader/XImplementationLoader.hpp>
63 #include <com/sun/star/registry/XRegistryKey.hpp>
64 #include <com/sun/star/bridge/XUnoUrlResolver.hpp>
65 #include <com/sun/star/container/XSet.hpp>
66 #include <com/sun/star/test/performance/XPerformanceTest.hpp>
67 
68 #define NLOOP 200000000
69 
70 using namespace rtl;
71 using namespace osl;
72 using namespace cppu;
73 using namespace com::sun::star::uno;
74 using namespace com::sun::star::lang;
75 using namespace com::sun::star::loader;
76 using namespace com::sun::star::registry;
77 using namespace com::sun::star::bridge;
78 using namespace com::sun::star::container;
79 using namespace com::sun::star::test::performance;
80 
81 #define SERVICENAME		"com.sun.star.test.performance.PerformanceTest"
82 #define IMPLNAME		"com.sun.star.comp.performance.PerformanceTest"
83 
84 namespace benchmark_test
85 {
86 
getSystemTicks()87 static inline sal_uInt32 getSystemTicks()
88 {
89 #ifdef SAL_W32
90 	return (sal_uInt32)GetTickCount();
91 #else // only UNX supported for now
92 	static sal_uInt32	nImplTicksPerSecond = 0;
93 	static double		dImplTicksPerSecond;
94 	static double		dImplTicksULONGMAX;
95 
96 	struct tms			aTms;
97 	sal_uInt32 nTicks = (sal_uInt32)times( &aTms );
98 
99 	if ( !nImplTicksPerSecond )
100 	{
101 		nImplTicksPerSecond = sysconf(_SC_CLK_TCK);
102 		dImplTicksPerSecond = nImplTicksPerSecond;
103 		dImplTicksULONGMAX	= (double)(sal_uInt32)ULONG_MAX;
104 	}
105 
106 	double fTicks = nTicks;
107 	fTicks *= 1000;
108 	fTicks /= dImplTicksPerSecond;
109 	fTicks = fmod (fTicks, dImplTicksULONGMAX);
110 
111 	return (sal_uInt32)fTicks;
112 #endif
113 }
114 
115 //--------------------------------------------------------------------------------------------------
out(const sal_Char * pText,FILE * stream=stderr,sal_Int32 nStart=-1,sal_Char cFillchar=' ')116 static void out( const sal_Char * pText, FILE * stream = stderr,
117 				 sal_Int32 nStart = -1, sal_Char cFillchar = ' ' )
118 {
119 	static sal_Int32 s_nPos = 0;
120 
121 	sal_Char ar[2] = { cFillchar, 0 };
122 	while (s_nPos < nStart)
123 	{
124 		::fprintf( stream, ar );
125 		++s_nPos;
126 	}
127 
128 	::fprintf( stream, pText );
129 
130 	for ( const sal_Char * p = pText; *p; ++p )
131 	{
132 		if (*p == '\n')
133 			s_nPos = 0;
134 		else
135 			++s_nPos;
136 	}
137 }
138 //--------------------------------------------------------------------------------------------------
out(const OUString & rText,FILE * stream=stderr,sal_Int32 nStart=-1,sal_Char cFillchar=' ')139 static inline void out( const OUString & rText, FILE * stream = stderr,
140 						sal_Int32 nStart = -1, sal_Char cFillchar = ' ' )
141 {
142 	OString aText( OUStringToOString( rText, RTL_TEXTENCODING_ASCII_US ) );
143 	out( aText.getStr(), stream, nStart, cFillchar );
144 }
145 //--------------------------------------------------------------------------------------------------
out(double fVal,FILE * stream=stderr,sal_Int32 nStart=-1,sal_Char cFillchar=' ')146 static inline void out( double fVal, FILE * stream = stderr,
147 						sal_Int32 nStart = -1, sal_Char cFillchar = ' ' )
148 {
149 	sal_Char ar[128];
150     ::snprintf( ar, sizeof(ar), (fVal < 0.000001 ? "%g" : "%f"), fVal );
151 	out( ar, stream, nStart, cFillchar );
152 }
153 //--------------------------------------------------------------------------------------------------
out(sal_Int64 nVal,FILE * stream=stderr,sal_Int32 nStart=-1,sal_Char cFillchar=' ')154 static inline void out( sal_Int64 nVal, FILE * stream = stderr,
155 						sal_Int32 nStart = -1, sal_Char cFillchar = ' ' )
156 {
157 	sal_Char ar[128];
158     ::snprintf( ar, sizeof(ar), "%ld", nVal );
159 	out( ar, stream, nStart, cFillchar );
160 }
161 
162 //==================================================================================================
loadLibComponentFactory(const OUString & rLibName,const OUString & rImplName,const Reference<XMultiServiceFactory> & xSF,const Reference<XRegistryKey> & xKey)163 Reference< XSingleServiceFactory > loadLibComponentFactory(
164 	const OUString & rLibName, const OUString & rImplName,
165 	const Reference< XMultiServiceFactory > & xSF, const Reference< XRegistryKey > & xKey )
166 {
167 	Reference< XSingleServiceFactory > xRet;
168 
169 	OUStringBuffer aLibNameBuf( 32 );
170 #ifdef SAL_UNX
171 	aLibNameBuf.appendAscii( RTL_CONSTASCII_STRINGPARAM("lib") );
172 	aLibNameBuf.append( rLibName );
173 	aLibNameBuf.appendAscii( RTL_CONSTASCII_STRINGPARAM(".so") );
174 #else
175 	aLibNameBuf.append( rLibName );
176 	aLibNameBuf.appendAscii( RTL_CONSTASCII_STRINGPARAM(".dll") );
177 #endif
178 	OUString aLibName( aLibNameBuf.makeStringAndClear() );
179 	oslModule lib = osl_loadModule( aLibName.pData, SAL_LOADMODULE_LAZY | SAL_LOADMODULE_GLOBAL );
180 
181 	if (lib)
182 	{
183 		void * pSym;
184 
185 		// ========================= LATEST VERSION =========================
186 		OUString aGetEnvName( RTL_CONSTASCII_USTRINGPARAM(COMPONENT_GETENV) );
187 		if (pSym = osl_getSymbol( lib, aGetEnvName.pData ))
188 		{
189 			uno_Environment * pCurrentEnv = 0;
190 			uno_Environment * pEnv = 0;
191 			const sal_Char * pEnvTypeName = 0;
192 			(*((component_getImplementationEnvironmentFunc)pSym))( &pEnvTypeName, &pEnv );
193 
194 			sal_Bool bNeedsMapping =
195 				(pEnv || 0 != rtl_str_compare( pEnvTypeName, CPPU_CURRENT_LANGUAGE_BINDING_NAME ));
196 
197 			OUString aEnvTypeName( OUString::createFromAscii( pEnvTypeName ) );
198 
199 			if (bNeedsMapping)
200 			{
201 				if (! pEnv)
202 					uno_getEnvironment( &pEnv, aEnvTypeName.pData, 0 );
203 				if (pEnv)
204 				{
205 					OUString aCppEnvTypeName( RTL_CONSTASCII_USTRINGPARAM(CPPU_CURRENT_LANGUAGE_BINDING_NAME) );
206 					uno_getEnvironment( &pCurrentEnv, aCppEnvTypeName.pData, 0 );
207 					if (pCurrentEnv)
208 						bNeedsMapping = (pEnv != pCurrentEnv);
209 				}
210 			}
211 
212 			OUString aGetFactoryName( RTL_CONSTASCII_USTRINGPARAM(COMPONENT_GETFACTORY) );
213 			if (pSym = osl_getSymbol( lib, aGetFactoryName.pData ))
214 			{
215 				OString aImplName( OUStringToOString( rImplName, RTL_TEXTENCODING_ASCII_US ) );
216 
217 				if (bNeedsMapping)
218 				{
219 					if (pEnv && pCurrentEnv)
220 					{
221 						Mapping aCurrent2Env( pCurrentEnv, pEnv );
222 						Mapping aEnv2Current( pEnv, pCurrentEnv );
223 
224 						if (aCurrent2Env.is() && aEnv2Current.is())
225 						{
226 							void * pSMgr = aCurrent2Env.mapInterface(
227 								xSF.get(), ::getCppuType( (const Reference< XMultiServiceFactory > *)0 ) );
228 							void * pKey = aCurrent2Env.mapInterface(
229 								xKey.get(), ::getCppuType( (const Reference< XRegistryKey > *)0 ) );
230 
231 							void * pSSF = (*((component_getFactoryFunc)pSym))(
232 								aImplName.getStr(), pSMgr, pKey );
233 
234 							if (pKey)
235 								(*pEnv->pExtEnv->releaseInterface)( pEnv->pExtEnv, pKey );
236 							if (pSMgr)
237 								(*pEnv->pExtEnv->releaseInterface)( pEnv->pExtEnv, pSMgr );
238 
239 							if (pSSF)
240 							{
241 								aEnv2Current.mapInterface(
242 									reinterpret_cast< void ** >( &xRet ),
243 									pSSF, ::getCppuType( (const Reference< XSingleServiceFactory > *)0 ) );
244 								(*pEnv->pExtEnv->releaseInterface)( pEnv->pExtEnv, pSSF );
245 							}
246 						}
247 					}
248 				}
249 				else
250 				{
251 					XSingleServiceFactory * pRet = (XSingleServiceFactory *)
252 						(*((component_getFactoryFunc)pSym))(
253 							aImplName.getStr(), xSF.get(), xKey.get() );
254 					if (pRet)
255 					{
256 						xRet = pRet;
257 						pRet->release();
258 					}
259 				}
260 			}
261 
262 			if (pEnv)
263 				(*pEnv->release)( pEnv );
264 			if (pCurrentEnv)
265 				(*pCurrentEnv->release)( pCurrentEnv );
266 		}
267 
268 		// ========================= PREVIOUS VERSION =========================
269 		else
270 		{
271 			OUString aGetFactoryName( RTL_CONSTASCII_USTRINGPARAM(CREATE_COMPONENT_FACTORY_FUNCTION) );
272 			if (pSym = osl_getSymbol( lib, aGetFactoryName.pData ))
273 			{
274 				OUString aCppEnvTypeName( RTL_CONSTASCII_USTRINGPARAM(CPPU_CURRENT_LANGUAGE_BINDING_NAME) );
275 				OUString aUnoEnvTypeName( RTL_CONSTASCII_USTRINGPARAM(UNO_LB_UNO) );
276 				Mapping aUno2Cpp( aUnoEnvTypeName, aCppEnvTypeName );
277 				Mapping aCpp2Uno( aCppEnvTypeName, aUnoEnvTypeName );
278 				OSL_ENSURE( aUno2Cpp.is() && aCpp2Uno.is(), "### cannot get uno mappings!" );
279 
280 				if (aUno2Cpp.is() && aCpp2Uno.is())
281 				{
282 					uno_Interface * pUComponentFactory = 0;
283 
284 					uno_Interface * pUSFactory = (uno_Interface *)aCpp2Uno.mapInterface(
285 						xSF.get(), ::getCppuType( (const Reference< XMultiServiceFactory > *)0 ) );
286 					uno_Interface * pUKey = (uno_Interface *)aCpp2Uno.mapInterface(
287 						xKey.get(), ::getCppuType( (const Reference< XRegistryKey > *)0 ) );
288 
289 					pUComponentFactory = (*((CreateComponentFactoryFunc)pSym))(
290 						rImplName.getStr(), pUSFactory, pUKey );
291 
292 					if (pUKey)
293 						(*pUKey->release)( pUKey );
294 					if (pUSFactory)
295 						(*pUSFactory->release)( pUSFactory );
296 
297 					if (pUComponentFactory)
298 					{
299 						XSingleServiceFactory * pXFactory =
300 							(XSingleServiceFactory *)aUno2Cpp.mapInterface(
301 								pUComponentFactory, ::getCppuType( (const Reference< XSingleServiceFactory > *)0 ) );
302 						(*pUComponentFactory->release)( pUComponentFactory );
303 
304 						if (pXFactory)
305 						{
306 							xRet = pXFactory;
307 							pXFactory->release();
308 						}
309 					}
310 				}
311 			}
312 		}
313 
314 		if (! xRet.is())
315 			osl_unloadModule( lib );
316 	}
317 
318 	return xRet;
319 }
320 //--------------------------------------------------------------------------------------------------
321 template< class T >
createInstance(Reference<T> & rxOut,const Reference<XMultiServiceFactory> & xMgr,const OUString & rServiceName)322 static void createInstance( Reference< T > & rxOut,
323 							const Reference< XMultiServiceFactory > & xMgr,
324 							const OUString & rServiceName )
325 	throw (RuntimeException)
326 {
327 	Reference< XInterface > x( xMgr->createInstance( rServiceName ), UNO_QUERY );
328 
329 	if (! x.is())
330 	{
331 		static sal_Bool s_bSet = sal_False;
332 		if (! s_bSet)
333 		{
334 			MutexGuard aGuard( Mutex::getGlobalMutex() );
335 			if (! s_bSet)
336 			{
337 				Reference< XSet > xSet( xMgr, UNO_QUERY );
338 				if (xSet.is())
339 				{
340 					// acceptor
341 					xSet->insert( makeAny( loadLibComponentFactory(
342 						OUString( RTL_CONSTASCII_USTRINGPARAM("acceptor") ),
343 						OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.stoc.Acceptor") ),
344 						xMgr, Reference< XRegistryKey >() ) ) );
345 					// connector
346 					xSet->insert( makeAny( loadLibComponentFactory(
347 						OUString( RTL_CONSTASCII_USTRINGPARAM("connectr") ),
348 						OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.stoc.Connector") ),
349 						xMgr, Reference< XRegistryKey >() ) ) );
350 					// iiop bridge
351 					xSet->insert( makeAny( loadLibComponentFactory(
352 						OUString( RTL_CONSTASCII_USTRINGPARAM("remotebridge") ),
353 						OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.bridge.Bridge.various") ),
354 						xMgr, Reference< XRegistryKey >() ) ) );
355 					// bridge factory
356 					xSet->insert( makeAny( loadLibComponentFactory(
357 						OUString( RTL_CONSTASCII_USTRINGPARAM("brdgfctr") ),
358 						OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.stoc.BridgeFactory") ),
359 						xMgr, Reference< XRegistryKey >() ) ) );
360 					// uno url resolver
361 					xSet->insert( makeAny( loadLibComponentFactory(
362 						OUString( RTL_CONSTASCII_USTRINGPARAM("uuresolver") ),
363 						OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.bridge.UnoUrlResolver") ),
364 						xMgr, Reference< XRegistryKey >() ) ) );
365 					// java loader
366 //  					xSet->insert( makeAny( loadLibComponentFactory(
367 //  						OUString( RTL_CONSTASCII_USTRINGPARAM("javaloader") ),
368 //  						OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.stoc.JavaComponentLoader") ),
369 //  						xMgr, Reference< XRegistryKey >() ) ) );
370 				}
371 				s_bSet = sal_True;
372 			}
373 		}
374 		x = xMgr->createInstance( rServiceName );
375 	}
376 
377 	if (! x.is())
378 	{
379 		OUStringBuffer buf( 64 );
380 		buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("cannot get service instance \"") );
381 		buf.append( rServiceName );
382 		buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\"!") );
383 		throw RuntimeException( buf.makeStringAndClear(), Reference< XInterface >() );
384 	}
385 
386 	rxOut = Reference< T >::query( x );
387 	if (! rxOut.is())
388 	{
389 		OUStringBuffer buf( 64 );
390 		buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("service instance \"") );
391 		buf.append( rServiceName );
392 		buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\" does not support demanded interface \"") );
393 		const Type & rType = ::getCppuType( (const Reference< T > *)0 );
394 		buf.append( rType.getTypeName() );
395 		buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\"!") );
396 		throw RuntimeException( buf.makeStringAndClear(), Reference< XInterface >() );
397 	}
398 }
399 
400 //--------------------------------------------------------------------------------------------------
getSupportedServiceNames()401 inline static Sequence< OUString > getSupportedServiceNames()
402 {
403 	OUString aName( RTL_CONSTASCII_USTRINGPARAM(SERVICENAME) );
404 	return Sequence< OUString >( &aName, 1 );
405 }
406 
407 //==================================================================================================
408 class TestImpl : public WeakImplHelper2< XServiceInfo, XMain >
409 {
410 	Reference< XMultiServiceFactory > _xSMgr;
411 
412 	Reference< XInterface > _xDirect;
413 	Reference< XInterface > getDirect() throw (Exception);
414 	Reference< XInterface > resolveObject( const OUString & rUnoUrl ) throw (Exception);
415 
416 public:
417 	TestImpl( const Reference< XMultiServiceFactory > & xSMgr );
418 	virtual ~TestImpl();
419 
420 	// XServiceInfo
421 	virtual OUString SAL_CALL getImplementationName() throw (RuntimeException);
422 	virtual sal_Bool SAL_CALL supportsService( const OUString & rServiceName ) throw (RuntimeException);
423 	virtual Sequence< OUString > SAL_CALL getSupportedServiceNames() throw (RuntimeException);
424 
425 	// XMain
426     virtual sal_Int32 SAL_CALL run( const Sequence< OUString > & rArgs ) throw (RuntimeException);
427 };
428 
429 //##################################################################################################
430 
431 //__________________________________________________________________________________________________
TestImpl(const Reference<XMultiServiceFactory> & xSMgr)432 TestImpl::TestImpl( const Reference< XMultiServiceFactory > & xSMgr )
433 	: _xSMgr( xSMgr )
434 {
435 }
436 //__________________________________________________________________________________________________
~TestImpl()437 TestImpl::~TestImpl()
438 {
439 }
440 
441 //==================================================================================================
TestImpl_create(const Reference<XMultiServiceFactory> & xSMgr)442 static Reference< XInterface > SAL_CALL TestImpl_create( const Reference< XMultiServiceFactory > & xSMgr )
443 {
444 	return Reference< XInterface >( *new TestImpl( xSMgr ) );
445 }
446 
447 // XServiceInfo
448 //__________________________________________________________________________________________________
getImplementationName()449 OUString TestImpl::getImplementationName()
450 	throw (RuntimeException)
451 {
452 	return OUString( RTL_CONSTASCII_USTRINGPARAM(IMPLNAME) );
453 }
454 //__________________________________________________________________________________________________
supportsService(const OUString & rServiceName)455 sal_Bool TestImpl::supportsService( const OUString & rServiceName )
456 	throw (RuntimeException)
457 {
458 	const Sequence< OUString > & rSNL = getSupportedServiceNames();
459 	const OUString * pArray = rSNL.getConstArray();
460 	for ( sal_Int32 nPos = rSNL.getLength(); nPos--; )
461 	{
462 		if (pArray[nPos] == rServiceName)
463 			return sal_True;
464 	}
465 	return sal_False;
466 }
467 //__________________________________________________________________________________________________
getSupportedServiceNames()468 Sequence< OUString > TestImpl::getSupportedServiceNames()
469 	throw (RuntimeException)
470 {
471 	return benchmark_test::getSupportedServiceNames();
472 }
473 
474 //__________________________________________________________________________________________________
getDirect()475 Reference< XInterface > TestImpl::getDirect()
476 	throw (Exception)
477 {
478 	if (! _xDirect.is())
479 	{
480 		MutexGuard aGuard( Mutex::getGlobalMutex() );
481 		if (! _xDirect.is())
482 		{
483 			Reference< XSingleServiceFactory > xFac( loadLibComponentFactory(
484 				OUString( RTL_CONSTASCII_USTRINGPARAM("perfobj") ),
485 				OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.performance.PerformanceTestObject") ),
486 				_xSMgr, Reference< XRegistryKey >() ) );
487 			if (! xFac.is())
488 				throw RuntimeException( OUString( RTL_CONSTASCII_USTRINGPARAM("no test object available!") ), Reference< XInterface >() );
489 			_xDirect = xFac->createInstance();
490 		}
491 	}
492 	return _xDirect;
493 }
494 //--------------------------------------------------------------------------------------------------
resolveObject(const OUString & rUnoUrl)495 Reference< XInterface > TestImpl::resolveObject( const OUString & rUnoUrl )
496 	throw (Exception)
497 {
498 	Reference< XUnoUrlResolver > xResolver;
499 	createInstance(
500 		xResolver, _xSMgr,
501 		OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.bridge.UnoUrlResolver") ) );
502 
503 	Reference< XInterface > xResolvedObject( xResolver->resolve( rUnoUrl ) );
504 
505 	if (! xResolvedObject.is())
506 	{
507 		OUStringBuffer buf( 32 );
508 		buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("cannot resolve object \"") );
509 		buf.append( rUnoUrl );
510 		buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\"!") );
511 		throw RuntimeException( buf.makeStringAndClear(), Reference< XInterface >() );
512 	}
513 
514 	return xResolvedObject;
515 }
516 
517 //==================================================================================================
518 class TimeEntry
519 {
520 	sal_Int64			nLoop;
521 	sal_uInt32			nTicks;
522 
523 public:
TimeEntry()524 	TimeEntry()
525 		{}
TimeEntry(sal_Int64 nLoop_,sal_uInt32 nTicks_)526 	TimeEntry( sal_Int64 nLoop_, sal_uInt32 nTicks_ )
527 		: nLoop( nLoop_ )
528 		, nTicks( nTicks_ )
529 		{}
530 
secPerCall() const531 	inline double secPerCall() const
532 		{ return (((double)nTicks) / (nLoop * 1000)); }
533 
534 	double ratio( const TimeEntry & rEntry ) const;
535 };
536 //__________________________________________________________________________________________________
ratio(const TimeEntry & rEntry) const537 double TimeEntry::ratio( const TimeEntry & rEntry ) const
538 {
539 	double f = rEntry.nTicks * nLoop;
540 	if (f == 0.0)
541 	{
542 		return 0.0;
543 	}
544 	else
545 	{
546 		return (((double)(nTicks * rEntry.nLoop)) / f);
547 	}
548 }
549 
550 //==================================================================================================
551 typedef std::map< std::string, TimeEntry > t_TimeEntryMap;
552 
553 //==================================================================================================
554 struct TimingSheet
555 {
556 	t_TimeEntryMap		_entries;
557 	void insert( const sal_Char * pText, sal_Int64 nLoop, sal_uInt32 nTicks );
558 };
559 //__________________________________________________________________________________________________
insert(const sal_Char * pText,sal_Int64 nLoop,sal_uInt32 nTicks)560 void TimingSheet::insert( const sal_Char * pText, sal_Int64 nLoop, sal_uInt32 nTicks )
561 {
562 	_entries[ pText ] = TimeEntry( nLoop, nTicks );
563 }
564 
565 //==================================================================================================
566 typedef std::hash_map< std::string, TimingSheet > t_TimingSheetMap;
567 
568 //--------------------------------------------------------------------------------------------------
benchmark(TimingSheet & rSheet,const Reference<XInterface> & xInstance,sal_Int64 nLoop)569 static void benchmark(
570 	TimingSheet & rSheet, const Reference< XInterface > & xInstance, sal_Int64 nLoop )
571 	throw (Exception)
572 {
573 	Reference< XPerformanceTest > xBench( xInstance, UNO_QUERY );
574 	if (! xBench.is())
575 		throw RuntimeException( OUString( RTL_CONSTASCII_USTRINGPARAM("illegal test object!") ), Reference< XInterface >() );
576 
577 	sal_Int64 i;
578 	sal_uInt32 tStart, tEnd;
579 
580 	const Type & rKnownType = ::getCppuType( (const Reference< XPerformanceTest > *)0 );
581 	const Type & rUnKnownType = ::getCppuType( (const Reference< XSet > *)0 );
582 
583 	ComplexTypes aDummyStruct;
584 
585 	//------------------------------------
586 	// oneway calls
587 	i = nLoop;
588 	tStart = getSystemTicks();
589 	while (i--)
590 		xBench->async();
591 	sal_uInt32 tEndSend = getSystemTicks();
592 	xBench->sync();
593 	tEnd = getSystemTicks();
594 	rSheet.insert( "1a: sending simple oneway calls (no params, no return)", nLoop, tEndSend - tStart );
595 	rSheet.insert( "1b: simple oneway calls (no params, no return)", nLoop, tEnd - tStart );
596 	// synchron calls
597 	i = nLoop;
598 	tStart = getSystemTicks();
599 	while (i--)
600 		xBench->sync();
601 	xBench->sync();
602 	tEnd = getSystemTicks();
603 	rSheet.insert( "1c: simple synchron calls (no params no return)", nLoop+1, tEnd - tStart );
604 
605 	// acquire
606 	i = nLoop;
607 	tStart = getSystemTicks();
608 	while (i--)
609 		xBench->acquire();
610 	tEnd = getSystemTicks();
611 	rSheet.insert( "2a: interface acquire() calls", nLoop, tEnd - tStart );
612 	// release
613 	i = nLoop;
614 	tStart = getSystemTicks();
615 	while (i--)
616 		xBench->release();
617 	tEnd = getSystemTicks();
618 	rSheet.insert( "2b: interface release() calls", nLoop, tEnd - tStart );
619 
620 	// queryInterface() for known type
621 	i = nLoop;
622 	tStart = getSystemTicks();
623 	while (i--)
624 		xBench->queryInterface( rKnownType );
625 	tEnd = getSystemTicks();
626 	rSheet.insert( "2c: interface query for implemented type", nLoop, tEnd - tStart );
627 	// queryInterface() for unknown type
628 	i = nLoop;
629 	tStart = getSystemTicks();
630 	while (i--)
631 		xBench->queryInterface( rUnKnownType );
632 	tEnd = getSystemTicks();
633 	rSheet.insert( "2d: interface query for unknown type", nLoop, tEnd - tStart );
634 
635 	// create and forget objects
636 	Reference< XPerformanceTest > xBench2( xBench );
637 	i = nLoop;
638 	tStart = getSystemTicks();
639 	while (i--)
640 		xBench2 = xBench2->createObject();
641 	tEnd = getSystemTicks();
642 	rSheet.insert( "3a: create and release test objects", nLoop, tEnd - tStart );
643 
644 	// hold new objects
645 	Sequence< Reference< XInterface > > aSeq( nLoop / 100 );
646 	Reference< XInterface > * pSeq = aSeq.getArray();
647 	xBench2 = xBench;
648 	i = aSeq.getLength();
649 	tStart = getSystemTicks();
650 	while (i--)
651 		pSeq[i] = xBench2 = xBench2->createObject();
652 	tEnd = getSystemTicks();
653 	rSheet.insert( "3b: create and hold test objects", nLoop, tEnd - tStart );
654 
655 	// structs
656 	i = nLoop;
657 	tStart = getSystemTicks();
658 	while (i--)
659 		xBench->complex_in( aDummyStruct );
660 	tEnd = getSystemTicks();
661 	rSheet.insert( "4a: complex_in() calls (in struct; return struct)", nLoop, tEnd - tStart );
662 	i = nLoop;
663 	tStart = getSystemTicks();
664 	while (i--)
665 		xBench->complex_inout( aDummyStruct );
666 	tEnd = getSystemTicks();
667 	rSheet.insert( "4b: complex_inout() calls (inout struct; return struct)", nLoop, tEnd - tStart );
668 
669 	i = nLoop;
670 	tStart = getSystemTicks();
671 	while (i--)
672 		xBench->complex_oneway( aDummyStruct );
673 	tEnd = getSystemTicks();
674 	rSheet.insert( "4c: complex_oneway() oneway calls (in struct)", nLoop, tEnd - tStart );
675 	i = nLoop;
676 	tStart = getSystemTicks();
677 	while (i--)
678 		xBench->complex_noreturn( aDummyStruct );
679 	tEnd = getSystemTicks();
680 	rSheet.insert( "4d: complex_noreturn() calls (in struct)", nLoop, tEnd - tStart );
681 
682 	// attributes, get() methods
683 	i = nLoop;
684 	tStart = getSystemTicks();
685 	while (i--)
686 		xBench->getLong();
687 	tEnd = getSystemTicks();
688 	rSheet.insert( "5a: getLong() call", nLoop, tEnd - tStart );
689 	i = nLoop;
690 	tStart = getSystemTicks();
691 	while (i--)
692 		xBench->getLong_attr();
693 	tEnd = getSystemTicks();
694 	rSheet.insert( "5b: get long attribute", nLoop, tEnd - tStart );
695 
696 	i = nLoop;
697 	tStart = getSystemTicks();
698 	while (i--)
699 		xBench->setLong( 0 );
700 	tEnd = getSystemTicks();
701 	rSheet.insert( "5c: setLong() call", nLoop, tEnd - tStart );
702 	i = nLoop;
703 	tStart = getSystemTicks();
704 	while (i--)
705 		xBench->setLong_attr( 0 );
706 	tEnd = getSystemTicks();
707 	rSheet.insert( "5d: set long attribute", nLoop, tEnd - tStart );
708 
709 	i = nLoop;
710 	tStart = getSystemTicks();
711 	while (i--)
712 		xBench->getHyper();
713 	tEnd = getSystemTicks();
714 	rSheet.insert( "5e: getHyper() call", nLoop, tEnd - tStart );
715 	i = nLoop;
716 	tStart = getSystemTicks();
717 	while (i--)
718 		xBench->getHyper_attr();
719 	tEnd = getSystemTicks();
720 	rSheet.insert( "5f: get hyper attribute", nLoop, tEnd - tStart );
721 
722 	i = nLoop;
723 	tStart = getSystemTicks();
724 	while (i--)
725 		xBench->setHyper( 0 );
726 	tEnd = getSystemTicks();
727 	rSheet.insert( "5g: setHyper() call", nLoop, tEnd - tStart );
728 	i = nLoop;
729 	tStart = getSystemTicks();
730 	while (i--)
731 		xBench->setHyper_attr( 0 );
732 	tEnd = getSystemTicks();
733 	rSheet.insert( "5h: set hyper attribute", nLoop, tEnd - tStart );
734 
735 	i = nLoop;
736 	tStart = getSystemTicks();
737 	while (i--)
738 		xBench->getFloat();
739 	tEnd = getSystemTicks();
740 	rSheet.insert( "5i: getFloat() call", nLoop, tEnd - tStart );
741 	i = nLoop;
742 	tStart = getSystemTicks();
743 	while (i--)
744 		xBench->getFloat_attr();
745 	tEnd = getSystemTicks();
746 	rSheet.insert( "5j: get float attribute",nLoop,  tEnd - tStart );
747 
748 	i = nLoop;
749 	tStart = getSystemTicks();
750 	while (i--)
751 		xBench->setFloat( 0.0 );
752 	tEnd = getSystemTicks();
753 	rSheet.insert( "5k: setFloat() call", nLoop, tEnd - tStart );
754 	i = nLoop;
755 	tStart = getSystemTicks();
756 	while (i--)
757 		xBench->setFloat_attr( 0.0 );
758 	tEnd = getSystemTicks();
759 	rSheet.insert( "5l: set float attribute", nLoop, tEnd - tStart );
760 
761 	i = nLoop;
762 	tStart = getSystemTicks();
763 	while (i--)
764 		xBench->getDouble();
765 	tEnd = getSystemTicks();
766 	rSheet.insert( "5m: getDouble() call", nLoop, tEnd - tStart );
767 	i = nLoop;
768 	tStart = getSystemTicks();
769 	while (i--)
770 		xBench->getDouble_attr();
771 	tEnd = getSystemTicks();
772 	rSheet.insert( "5n: get double attribute", nLoop, tEnd - tStart );
773 	i = nLoop;
774 	tStart = getSystemTicks();
775 	while (i--)
776 		xBench->setDouble( 0.0 );
777 	tEnd = getSystemTicks();
778 	rSheet.insert( "5o: setDouble() call", nLoop, tEnd - tStart );
779 	i = nLoop;
780 	tStart = getSystemTicks();
781 	while (i--)
782 		xBench->setDouble_attr( 0.0 );
783 	tEnd = getSystemTicks();
784 	rSheet.insert( "5p: set double attribute", nLoop, tEnd - tStart );
785 
786 	i = nLoop;
787 	tStart = getSystemTicks();
788 	while (i--)
789 		xBench->getString();
790 	tEnd = getSystemTicks();
791 	rSheet.insert( "6a: getString() call (empty)", nLoop, tEnd - tStart );
792 	i = nLoop;
793 	tStart = getSystemTicks();
794 	while (i--)
795 		xBench->getString_attr();
796 	tEnd = getSystemTicks();
797 	rSheet.insert( "6b: get empty string attribute", nLoop, tEnd - tStart );
798 
799 	i = nLoop;
800 	OUString aDummyString;
801 	tStart = getSystemTicks();
802 	while (i--)
803 		xBench->setString( aDummyString );
804 	tEnd = getSystemTicks();
805 	rSheet.insert( "6c: setString() call (emtpy)", nLoop, tEnd - tStart );
806 	i = nLoop;
807 	tStart = getSystemTicks();
808 	while (i--)
809 		xBench->setString_attr( aDummyString );
810 	tEnd = getSystemTicks();
811 	rSheet.insert( "6d: set empty string attribute", nLoop, tEnd - tStart );
812 
813 	i = nLoop;
814 	tStart = getSystemTicks();
815 	while (i--)
816 		xBench->getInterface();
817 	tEnd = getSystemTicks();
818 	rSheet.insert( "7a: getInterface() call (null)", nLoop, tEnd - tStart );
819 	i = nLoop;
820 	tStart = getSystemTicks();
821 	while (i--)
822 		xBench->getInterface_attr();
823 	tEnd = getSystemTicks();
824 	rSheet.insert( "7b: get interface attribute", nLoop, tEnd - tStart );
825 
826 	i = nLoop;
827 	Reference< XInterface > aDummyInterface;
828 	tStart = getSystemTicks();
829 	while (i--)
830 		xBench->setInterface( aDummyInterface );
831 	tEnd = getSystemTicks();
832 	rSheet.insert( "7c: setInterface() call (null)", nLoop, tEnd - tStart );
833 	i = nLoop;
834 	tStart = getSystemTicks();
835 	while (i--)
836 		xBench->setInterface_attr( Reference< XInterface >() );
837 	tEnd = getSystemTicks();
838 	rSheet.insert( "7d: set interface attribute", nLoop, tEnd - tStart );
839 
840 	i = nLoop;
841 	tStart = getSystemTicks();
842 	while (i--)
843 		xBench->getAny();
844 	tEnd = getSystemTicks();
845 	rSheet.insert( "8a: getAny() call (empty)", nLoop, tEnd - tStart );
846 	i = nLoop;
847 	tStart = getSystemTicks();
848 	while (i--)
849 		xBench->getAny_attr();
850 	tEnd = getSystemTicks();
851 	rSheet.insert( "8b: get empty any attribute", nLoop, tEnd - tStart );
852 
853 	i = nLoop;
854 	Any aDummyAny;
855 	tStart = getSystemTicks();
856 	while (i--)
857 		xBench->setAny( aDummyAny );
858 	tEnd = getSystemTicks();
859 	rSheet.insert( "8c: setAny() call (empty)", nLoop, tEnd - tStart );
860 	i = nLoop;
861 	tStart = getSystemTicks();
862 	while (i--)
863 		xBench->setAny_attr( aDummyAny );
864 	tEnd = getSystemTicks();
865 	rSheet.insert( "8d: set empty any attribute", nLoop, tEnd - tStart );
866 
867 	i = nLoop;
868 	tStart = getSystemTicks();
869 	while (i--)
870 		xBench->getSequence();
871 	tEnd = getSystemTicks();
872 	rSheet.insert( "9a: getSequence() call (empty)", nLoop, tEnd - tStart );
873 	i = nLoop;
874 	tStart = getSystemTicks();
875 	while (i--)
876 		xBench->getSequence_attr();
877 	tEnd = getSystemTicks();
878 	rSheet.insert( "9b: get empty sequence attribute", nLoop, tEnd - tStart );
879 	i = nLoop;
880 	Sequence< Reference< XInterface > > aDummySeq;
881 	tStart = getSystemTicks();
882 	while (i--)
883 		xBench->setSequence( aDummySeq );
884 	tEnd = getSystemTicks();
885 	rSheet.insert( "9c: setSequence() call (empty)", nLoop, tEnd - tStart );
886 	i = nLoop;
887 	tStart = getSystemTicks();
888 	while (i--)
889 		xBench->setSequence_attr( aDummySeq );
890 	tEnd = getSystemTicks();
891 	rSheet.insert( "9d: set empty sequence attribute", nLoop, tEnd - tStart );
892 
893 	i = nLoop;
894 	tStart = getSystemTicks();
895 	while (i--)
896 		xBench->getStruct();
897 	tEnd = getSystemTicks();
898 	rSheet.insert( "Aa: getStruct() call", nLoop, tEnd - tStart );
899 	i = nLoop;
900 	tStart = getSystemTicks();
901 	while (i--)
902 		xBench->getStruct_attr();
903 	tEnd = getSystemTicks();
904 	rSheet.insert( "Ab: get struct attribute", nLoop, tEnd - tStart );
905 
906 	i = nLoop;
907 	tStart = getSystemTicks();
908 	while (i--)
909 		xBench->setStruct( aDummyStruct );
910 	tEnd = getSystemTicks();
911 	rSheet.insert( "Ac: setStruct() call", nLoop, tEnd - tStart );
912 	i = nLoop;
913 	tStart = getSystemTicks();
914 	while (i--)
915 		xBench->setStruct_attr( aDummyStruct );
916 	tEnd = getSystemTicks();
917 	rSheet.insert( "Ad: set struct attribute", nLoop, tEnd - tStart );
918 
919 	// load
920 //  	i = nLoop;
921 //  	tStart = getSystemTicks();
922 //  	while (i--)
923 //  		xBench->setSequence( aSeq );
924 //  	tEnd = getSystemTicks();
925 //  	rSheet.insert( "transfer of exisiting objects", nLoop, tEnd - tStart );
926 
927 	// exceptions
928 	i = nLoop;
929 	tStart = getSystemTicks();
930 	while (i--)
931 	{
932 		try
933 		{
934 			xBench->raiseRuntimeException();
935 		}
936 		catch (RuntimeException &)
937 		{
938 		}
939 	}
940 	tEnd = getSystemTicks();
941 	rSheet.insert( "Ba: raising RuntimeException", nLoop, tEnd - tStart );
942 
943 	//------------------------------------
944 }
945 
946 //--------------------------------------------------------------------------------------------------
extractParam(const Sequence<OUString> & rArgs,const OUString & rParam)947 static OUString extractParam( const Sequence< OUString > & rArgs, const OUString & rParam )
948 {
949 	const OUString * pArgs = rArgs.getConstArray();
950 	for ( sal_Int32 nPos = rArgs.getLength(); nPos--; )
951 	{
952 		if (pArgs[nPos].indexOf( rParam ) == 0 &&
953 			pArgs[nPos].getLength() > (rParam.getLength()+1))
954 		{
955 			return pArgs[nPos].copy( rParam.getLength() +1 ); // XXX=bla
956 		}
957 	}
958 	return OUString();
959 }
960 
961 const sal_Int32 nMagicNumberDirect = 34000;
962 
963 //XMain
964 //__________________________________________________________________________________________________
run(const Sequence<OUString> & rArgs)965 sal_Int32 TestImpl::run( const Sequence< OUString > & rArgs )
966 	throw (RuntimeException)
967 {
968 	// defaults
969 	FILE * stream = stderr;
970 	sal_Int64 nLoop = NLOOP;
971 	OUString aArg( RTL_CONSTASCII_USTRINGPARAM("dms") );
972 
973 	try
974 	{
975 		OUString aLoopStr( extractParam( rArgs, OUString( RTL_CONSTASCII_USTRINGPARAM("loop") ) ) );
976 		if (aLoopStr.getLength())
977 		{
978 			sal_Int64 n = aLoopStr.toInt64();
979 			if (n > 0)
980 				nLoop = n;
981 		}
982 
983 		OUString aDurationStr( extractParam( rArgs , OUString( RTL_CONSTASCII_USTRINGPARAM("duration" ) ) ) );
984 		if( aDurationStr.getLength() )
985 		{
986 			sal_Int64 n = aDurationStr.toInt64();
987 			if( n >0 )
988 				nLoop = nMagicNumberDirect * n;
989 		}
990 
991 		OUString aLogStr( extractParam( rArgs, OUString( RTL_CONSTASCII_USTRINGPARAM("log") ) ) );
992 		if (aLogStr.getLength())
993 		{
994 			if (aLogStr.compareToAscii( "stderr" ) == 0)
995 			{
996 				stream = stderr;
997 			}
998 			else if (aLogStr.compareToAscii( "stdout" ) == 0)
999 			{
1000 				stream = stdout;
1001 			}
1002 			else
1003 			{
1004 				OString aFileName( OUStringToOString( aLogStr, RTL_TEXTENCODING_ASCII_US ) );
1005 				stream = ::fopen( aFileName.getStr(), "w" );
1006 				if (! stream)
1007 				{
1008 					OUStringBuffer buf( 32 );
1009 					buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("cannot open file for writing: \"") );
1010 					buf.append( aLogStr );
1011 					buf.appendAscii( RTL_CONSTASCII_STRINGPARAM("\"!") );
1012 					throw RuntimeException( buf.makeStringAndClear(), Reference< XInterface >() );
1013 				}
1014 			}
1015 		}
1016 
1017 		OUString aArgStr( extractParam( rArgs, OUString( RTL_CONSTASCII_USTRINGPARAM("opt") ) ) );
1018 		if (aArgStr.getLength())
1019 		{
1020 			aArg = aArgStr;
1021 		}
1022 
1023 		if (! rArgs.getLength())
1024 			out( "\n> no options given, using defaults" );
1025 
1026 		// params
1027 		out( "\n> opt=" );
1028 		out( aArg );
1029 		out( " log=" );
1030 		if (stream == stderr)
1031 			out( "stderr" );
1032 		else if (stream == stderr)
1033 			out( "stdout loop=" );
1034 		else
1035 			out( aLogStr );
1036 		out( " loop=" );
1037 		out( nLoop );
1038 		out( "\n" );
1039 		t_TimingSheetMap aSheets;
1040 		TimingSheet aDirect;
1041 
1042 		//------------------------------------------------------------------------------------------
1043 
1044 		if (aArg.indexOf( 'd' ) >= 0)
1045 		{
1046 			// in process direct test
1047 			sal_uInt32 nStart = getSystemTicks();
1048 			benchmark( aDirect, getDirect(), nLoop );
1049 			sal_uInt32 nEnd = getSystemTicks();
1050 			fprintf( stderr, "Duration (direct in process): %g s\n", (nEnd - nStart)/1000.  );
1051 		}
1052 
1053 		//------------------------------------------------------------------------------------------
1054 
1055 		if (aArg.indexOf( 'm' ) >= 0)
1056 		{
1057 			// in process uno dispatch
1058 			Environment aCppEnv, aAnoCppEnv;
1059 			OUString aCurrentLanguageBindingName( RTL_CONSTASCII_USTRINGPARAM(CPPU_CURRENT_LANGUAGE_BINDING_NAME) );
1060 			uno_getEnvironment( reinterpret_cast< uno_Environment ** >( &aCppEnv ),
1061 								aCurrentLanguageBindingName.pData, 0 );
1062 			// anonymous
1063 			uno_createEnvironment( reinterpret_cast< uno_Environment ** >( &aAnoCppEnv ),
1064 								   aCurrentLanguageBindingName.pData, 0 );
1065 
1066 			// pseudo mapping uno<->uno: does nothing!
1067 			Mapping aMapping( aCppEnv.get(), aAnoCppEnv.get(), OUString( RTL_CONSTASCII_USTRINGPARAM("pseudo") ) );
1068 			if (! aMapping.is())
1069 				throw RuntimeException( OUString( RTL_CONSTASCII_USTRINGPARAM("no pseudo mapping available!") ), Reference< XInterface >() );
1070 
1071 			Reference< XInterface > xMapped;
1072 			Reference< XInterface > xDirect( getDirect() );
1073 			aMapping.mapInterface( reinterpret_cast< void ** >( &xMapped ), xDirect.get(),
1074 								   ::getCppuType( &xDirect ) );
1075 			if (! xMapped.is())
1076 				throw RuntimeException( OUString( RTL_CONSTASCII_USTRINGPARAM("mapping object failed!") ), Reference< XInterface >() );
1077 
1078 			sal_uInt32 nStart = getSystemTicks();
1079 			benchmark( aSheets[ "mapped in process" ], xMapped, nLoop / 100 );
1080 			sal_uInt32 nEnd = getSystemTicks();
1081 			fprintf( stderr, "Duration (mapped in process): %g s\n", (nStart - nEnd)/1000. );
1082 		}
1083 
1084 		//------------------------------------------------------------------------------------------
1085 
1086 		if (aArg.indexOf( 's' ) >= 0)
1087 		{
1088 			// start server process
1089 			oslSecurity hSecurity = osl_getCurrentSecurity();
1090 			if (! hSecurity)
1091 				throw RuntimeException( OUString( RTL_CONSTASCII_USTRINGPARAM("cannot get current security handle!") ), Reference< XInterface >() );
1092 
1093 			OUString aArgs[] = {
1094 				OUString( RTL_CONSTASCII_USTRINGPARAM("-c") ),
1095 				OUString( RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.performance.PerformanceTestObject") ),
1096 				OUString( RTL_CONSTASCII_USTRINGPARAM("-l") ),
1097 #ifdef SAL_UNX
1098 				OUString( RTL_CONSTASCII_USTRINGPARAM("libperfobj.so") ),
1099 #else
1100 				OUString( RTL_CONSTASCII_USTRINGPARAM("perfobj.dll") ),
1101 #endif
1102 				OUString( RTL_CONSTASCII_USTRINGPARAM("-r") ),
1103 				OUString( RTL_CONSTASCII_USTRINGPARAM("applicat.rdb") ),
1104 				OUString( RTL_CONSTASCII_USTRINGPARAM("-u") ),
1105 				OUString( RTL_CONSTASCII_USTRINGPARAM("uno:socket,host=localhost,port=6000;iiop;TestRemoteObject") ),
1106 				OUString( RTL_CONSTASCII_USTRINGPARAM("--singleaccept") )
1107 			};
1108 			rtl_uString * pArgs[] = {
1109 				aArgs[0].pData,
1110 				aArgs[1].pData,
1111 				aArgs[2].pData,
1112 				aArgs[3].pData,
1113 				aArgs[4].pData,
1114 				aArgs[5].pData,
1115 				aArgs[6].pData,
1116 				aArgs[7].pData,
1117 				aArgs[8].pData,
1118 				aArgs[9].pData,
1119 			};
1120 
1121 			out( "\n> executing: \"uno" );
1122 			for ( sal_Int32 nPos = 0; nPos < (sizeof(aArgs) / sizeof(OUString)); ++nPos )
1123 			{
1124 				out( " " );
1125 				out( aArgs[nPos] );
1126 			}
1127 			out( "\" ..." );
1128 
1129 			oslProcess hProcess = 0;
1130 			OUString aUnoExe( RTL_CONSTASCII_USTRINGPARAM("uno") );
1131 			OUString aWorkingDir( RTL_CONSTASCII_USTRINGPARAM(".") );
1132 			osl_executeProcess(
1133 				aUnoExe.pData, pArgs, sizeof(aArgs) / sizeof(OUString),
1134 				osl_Process_SEARCHPATH | osl_Process_DETACHED | osl_Process_NORMAL,
1135 				hSecurity, aWorkingDir.pData, 0, 0, &hProcess );
1136 
1137 			osl_freeSecurityHandle( hSecurity );
1138 			if (! hProcess)
1139 				throw RuntimeException( OUString( RTL_CONSTASCII_USTRINGPARAM("cannot start server process!") ), Reference< XInterface >() );
1140 			osl_freeProcessHandle( hProcess );
1141 
1142 			// wait three seconds
1143 			TimeValue threeSeconds;
1144 			threeSeconds.Seconds = 3;
1145 			osl_waitThread( &threeSeconds );
1146 
1147 			// connect and resolve outer process object
1148 			Reference< XInterface > xResolvedObject( resolveObject( OUString(
1149 				RTL_CONSTASCII_USTRINGPARAM("uno:socket,host=localhost,port=6000;iiop;TestRemoteObject") ) ) );
1150 
1151 			benchmark( aSheets[ "remote same host" ], xResolvedObject, nLoop / 300 );
1152 		}
1153 
1154 		//------------------------------------------------------------------------------------------
1155 
1156 		if (aArg.indexOf( 'r' ) >= 0)
1157 		{
1158 			// remote
1159 			OUString aUnoUrl( extractParam( rArgs, OUString( RTL_CONSTASCII_USTRINGPARAM("url") ) ) );
1160 			if (! aUnoUrl.getLength())
1161 				throw RuntimeException( OUString( RTL_CONSTASCII_USTRINGPARAM("performance test r(emote) needs additional uno url!") ), Reference< XInterface >() );
1162 
1163 			// connect and resolve outer process object
1164 			Reference< XInterface > xResolvedObject( resolveObject( aUnoUrl ) );
1165 
1166 			sal_Int32 t1 = getSystemTicks();
1167 			OString o = OUStringToOString( aUnoUrl, RTL_TEXTENCODING_ASCII_US );
1168 			benchmark( aSheets[ o.getStr() ], xResolvedObject, nLoop / 900 );
1169 			sal_Int32 t2 = getSystemTicks();
1170 			fprintf( stderr, "Duration (%s): %g s\n", o.getStr(),(t2 - t1)/1000. );
1171 		}
1172 
1173 		//------------------------------------------------------------------------------------------
1174 
1175 		if (aArg.indexOf( 'j' ) >= 0)
1176 		{
1177 			// java
1178   			benchmark( aSheets[ "java in process" ],
1179 					   _xSMgr->createInstance(OUString(RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.benchmark.JavaTestObject"))),
1180 					   nLoop / 1000 );
1181 		}
1182 
1183 		//------------------------------------------------------------------------------------------
1184 		// dump out tables
1185 
1186 		out( "\nTimes( ratio to direct in process )", stream );
1187 #if OSL_DEBUG_LEVEL > 1
1188         out ("; compiled with OSL_DEBUG_LEVEL > 1", stream );
1189 #endif
1190 		out( ":", stream );
1191 
1192 		sal_Int32 nPos = 60;
1193 		out( "[direct in process]", stream, nPos );
1194 		t_TimingSheetMap::const_iterator iSheets( aSheets.begin() );
1195 		for ( ; iSheets != aSheets.end(); ++iSheets )
1196 		{
1197 			nPos += 40;
1198 			out( "[", stream, nPos );
1199 			out( (*iSheets).first.c_str(), stream );
1200 			out( "]", stream );
1201 		}
1202 		for ( t_TimeEntryMap::const_iterator iTopics( aDirect._entries.begin() );
1203 			  iTopics != aDirect._entries.end(); ++iTopics )
1204 		{
1205 			const std::string & rTopic = (*iTopics).first;
1206 
1207 			out( "\n", stream );
1208 			out( rTopic.c_str(), stream );
1209 
1210 			out( ":", stream, 58, '.' );
1211 
1212 			sal_Int32 nPos = 60;
1213 
1214 			double secs = (*iTopics).second.secPerCall();
1215 			if (secs > 0.0)
1216 			{
1217 				out( secs * 1000, stream, nPos );
1218 				out( "ms", stream );
1219 			}
1220 			else
1221 			{
1222 				out( "NA", stream, nPos );
1223 			}
1224 
1225 			iSheets = aSheets.begin();
1226 			for ( ; iSheets != aSheets.end(); ++iSheets )
1227 			{
1228 				const t_TimeEntryMap::const_iterator iFind( (*iSheets).second._entries.find( rTopic ) );
1229 				OSL_ENSURE( iFind != (*iSheets).second._entries.end(), "####" );
1230 
1231 				nPos += 40;
1232 
1233 				double secs = (*iFind).second.secPerCall();
1234 				if (secs != 0.0)
1235 				{
1236 					out( secs * 1000, stream, nPos );
1237 					out( "ms", stream );
1238 
1239 					out( " (", stream );
1240 					double ratio = (*iFind).second.ratio( (*iTopics).second );
1241 					if (ratio != 0.0)
1242 					{
1243 						out( ratio, stream );
1244 						out( " x)", stream );
1245 					}
1246 					else
1247 					{
1248 						out( "NA)", stream );
1249 					}
1250 				}
1251 				else
1252 				{
1253 					out( "NA", stream, nPos );
1254 				}
1255 			}
1256 		}
1257 	}
1258 	catch (Exception & rExc)
1259 	{
1260 		if (stream != stderr && stream != stdout)
1261 			::fclose( stream );
1262 		throw RuntimeException( rExc.Message, rExc.Context );
1263 	}
1264 
1265 	if (stream != stderr && stream != stdout)
1266 		::fclose( stream );
1267 
1268 	out( "\n> done.\n" );
1269 	return 0;
1270 }
1271 
1272 }
1273 
1274 
1275 //##################################################################################################
1276 //##################################################################################################
1277 //##################################################################################################
1278 
1279 
1280 extern "C"
1281 {
1282 //==================================================================================================
component_getImplementationEnvironment(const sal_Char ** ppEnvTypeName,uno_Environment ** ppEnv)1283 void SAL_CALL component_getImplementationEnvironment(
1284 	const sal_Char ** ppEnvTypeName, uno_Environment ** ppEnv )
1285 {
1286 	*ppEnvTypeName = CPPU_CURRENT_LANGUAGE_BINDING_NAME;
1287 }
1288 //==================================================================================================
component_writeInfo(void * pServiceManager,void * pRegistryKey)1289 sal_Bool SAL_CALL component_writeInfo(
1290 	void * pServiceManager, void * pRegistryKey )
1291 {
1292 	if (pRegistryKey)
1293 	{
1294 		try
1295 		{
1296 			Reference< XRegistryKey > xNewKey(
1297 				reinterpret_cast< XRegistryKey * >( pRegistryKey )->createKey(
1298 					OUString( RTL_CONSTASCII_USTRINGPARAM("/" IMPLNAME "/UNO/SERVICES") ) ) );
1299 			xNewKey->createKey( OUString( RTL_CONSTASCII_USTRINGPARAM(SERVICENAME) ) );
1300 
1301 			return sal_True;
1302 		}
1303 		catch (InvalidRegistryException &)
1304 		{
1305 			OSL_ENSURE( sal_False, "### InvalidRegistryException!" );
1306 		}
1307 	}
1308 	return sal_False;
1309 }
1310 //==================================================================================================
component_getFactory(const sal_Char * pImplName,void * pServiceManager,void * pRegistryKey)1311 void * SAL_CALL component_getFactory(
1312 	const sal_Char * pImplName, void * pServiceManager, void * pRegistryKey )
1313 {
1314 	void * pRet = 0;
1315 
1316 	if (pServiceManager && rtl_str_compare( pImplName, IMPLNAME ) == 0)
1317 	{
1318 		Reference< XSingleServiceFactory > xFactory( createSingleFactory(
1319 			reinterpret_cast< XMultiServiceFactory * >( pServiceManager ),
1320 			OUString( RTL_CONSTASCII_USTRINGPARAM(IMPLNAME) ),
1321 			benchmark_test::TestImpl_create,
1322 			benchmark_test::getSupportedServiceNames() ) );
1323 
1324 		if (xFactory.is())
1325 		{
1326 			xFactory->acquire();
1327 			pRet = xFactory.get();
1328 		}
1329 	}
1330 
1331 	return pRet;
1332 }
1333 }
1334