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