2008-10-05 03:29 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl)

* harbour/tests/speedtst.prg
    + added support for multiple usage of --exclude parameter
    + added support for --thread[=<num>] parameter which allows to set how
      many threads will be used to execute speed test. When =<num> is not
      given then each test loop is executed by separate thread, f.e.:
         ./speedtst --thread=3
      Now you can make tests looking for optimal for your system values.
      Please only remember that the total results shown by speedtst
      can be highly bound with the most expensive test loop which is
      finished only on one CPU
    + added support for --only=<testnums,...> parameter which allows to
      chose requested tests
    + added restricted parameter validation and syntax info
This commit is contained in:
Przemyslaw Czerpak
2008-10-05 01:29:54 +00:00
parent 628b9840f1
commit 0ebec8fe5b
2 changed files with 183 additions and 62 deletions

View File

@@ -8,6 +8,21 @@
2008-12-31 13:59 UTC+0100 Foo Bar (foo.bar foobar.org)
*/
2008-10-05 03:29 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl)
* harbour/tests/speedtst.prg
+ added support for multiple usage of --exclude parameter
+ added support for --thread[=<num>] parameter which allows to set how
many threads will be used to execute speed test. When =<num> is not
given then each test loop is executed by separate thread, f.e.:
./speedtst --thread=3
Now you can make tests looking for optimal for your system values.
Please only remember that the total results shown by speedtst
can be highly bound with the most expensive test loop which is
finished only on one CPU
+ added support for --only=<testnums,...> parameter which allows to
chose requested tests
+ added restricted parameter validation and syntax info
2008-10-04 21:23 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl)
* harbour/source/vm/fm.c
! do not build DL-MM when HB_FM_WIN32_ALLOC is set

View File

@@ -54,17 +54,66 @@
return { iif( <.info.>, <(info)>, #<testExp> ), time }
proc main( par1, par2 )
test( par1, par2 )
proc main( ... )
local aParams, nMT, cExclude, cParam, lSyntax, i
aParams := hb_aparams()
lSyntax := .f.
cExclude := ""
nMT := 0
for each cParam in aParams
cParam := lower( cParam )
if cParam = "--thread"
if substr( cParam, 9, 1 ) == "="
if isdigit( substr( cParam, 10, 1 ) )
nMT := val( substr( cParam, 10 ) )
elseif substr( cParam, 10 ) == "all"
nMT := -1
else
lSyntax = .t.
endif
elseif empty( substr( cParam, 9 ) )
nMT := -1
else
lSyntax = .t.
endif
elseif cParam = "--exclude="
if substr( cParam, 11 ) == "mem"
cExclude += "029 030 023 025 027 040 041 043 052 053 019 022 031 032 "
else
cExclude += strtran( strtran( strtran( substr( cParam, 11 ), ;
".", " " ), ".", " " ), "/", " " ) + " "
endif
elseif cParam = "--only="
cExclude := ""
for i := 1 to N_TESTS
if !strzero( i, 3 ) $ cParam
cExclude += strzero( i, 3 ) + " "
endif
next
else
lSyntax = .t.
endif
if lSyntax
? "Unknown option:", cParam
? "syntax:", hb_argv( 0 ), "[--thread[=<num>]] [--only=<test(s)>] [--exclude=<test(s)>]"
?
return
endif
next
test( nMT, cExclude )
return
#ifdef __XHARBOUR__
#xtranslate hb_mtvm() => hb_multiThread()
#xtranslate hb_threadWaitForAll() => WaitForThreads()
#xtranslate hb_mutexNotify(<x,...>) => Notify(<x>)
#ifndef __ST__
/* do not expect that this code will work with xHarbour.
* xHarbour has many race conditions which are exploited quite fast
* on real multi CPU machines so it crashes in different places :-(
@@ -72,50 +121,75 @@ return
* some type of MT test
*/
static function results( nTest, xResult )
static s_aResults[ N_TESTS + 1 ]
if xResult == NIL
xResult := s_aResults[ nTest ]
else
s_aResults[ nTest ] := xResult
endif
return xResult
/* I used function wrappers to simulate thread join which can
* return thread results
/* this define is only for test if emulation function works
* without running real test which causes that xHarbour crashes
*/
static function do_test( cFunc )
local x
? "starting: " + cFunc + "()"
// if you set .f. then tests will be skipped but you can check
// if this test code is executed because it greatly reduces
// the race conditions inside xHarbour HVM
if .t.
x := &cFunc()
//dsp_result( x )
else
x := { "skipped test " + cFunc, val( substr( cFunc, 2 ) ) + 0.99 }
endif
results( val( substr( cFunc, 2 ) ), x )
return nil
//#define _DUMY_XHB_TEST_
function hb_threadStart( cFunc )
return StartThread( @do_test(), cFunc )
function hb_mutexSubscribe( mtx, nTimeOut, xSubscribed )
local lSubscribed
if valtype( nTimeOut ) == "N"
nTimeOut := round( nTimeOut * 1000, 0 )
endif
xSubscribed := Subscribe( mtx, nTimeOut, @lSubscribed )
return lSubscribed
/* in xHarbour there is race condition in JoinThread() which
* fails if thread end before we call it so we cannot use it :-(
* this code tries to simulate it and also add support for thread
* return value
*/
function hb_threadStart( ... )
local thId
thId := StartThread( @threadFirstFunc(), hb_aParams() )
/* Just like in JoinThread() the same race condition exists in
* GetThreadId() so we will use HVM thread numbers internally
*/
#ifdef _DUMY_XHB_TEST_
return val( substr( hb_aParams()[1], 2 ) )
#else
return GetThreadId( thId )
#endif
function hb_threadJoin( thId, xResult )
static s_n := 0
local lOK
/* in xHarbour there is race condition in JoinThread() which
* fails if thread end before we call it so we cannot use it :-(
*/
//lOK := JoinThread( thId )
lOK := .t.
if s_n == 0
HB_SYMBOL_UNUSED( thId )
WaitForThreads()
xResult := results( thId )
return .t.
static function threadFirstFunc( aParams )
local xResult
#ifdef _DUMY_XHB_TEST_
xResult := { "skipped test " + aParams[1], val( substr( aParams[1], 2 ) ) + 0.99 }
results( val( substr( aParams[1], 2 ) ), xResult )
#else
xResult := hb_execFromArray( aParams )
results( GetThreadId(), xResult )
#endif
return nil
static function results( nThread, xResult )
static s_aResults
static s_mutex
if s_aResults == nil
s_aResults := HSetAutoAdd( hash(), .t. )
s_mutex := hb_mutexCreate()
endif
xResult := results( ++s_n )
return lOK
if pcount() < 2
while ! nThread $ s_aResults
Subscribe( s_mutex, 1000 )
enddo
xResult := s_aResults[ nThread ]
else
s_aResults[ nThread ] := xResult
/* We cannot use NotifyAll() here because it will create
* race condition. In this program only one thread join
* results so we can use simple Notify() as workaround
*/
//NotifyAll( s_mutex )
Notify( s_mutex )
endif
return xResult
#else
@@ -123,6 +197,14 @@ return
return nil
function hb_threadJoin()
return nil
function hb_mutexSubscribe()
return nil
function hb_mutexCreate()
return nil
function notify()
return nil
function waitForThreads()
return nil
#endif
@@ -285,24 +367,22 @@ TEST t052 CODE x := f4()
TEST t053 CODE x := f5()
proc test( par1, par2 )
local nLoopOverHead, nTimes, nSeconds, cExclude, cNum, lMT, x, i, aThreads:={}
function thTest( mtxJobs, aResults )
local xJob
while .T.
hb_mutexSubscribe( mtxJobs,, @xJob )
if xJob == NIL
exit
endif
aResults[ xJob ] := &( "t" + strzero( xJob, 3 ) )()
enddo
return nil
proc test( nMT, cExclude )
local nLoopOverHead, nTimes, nSeconds, cNum, aThreads, aResults, mtxJobs, x, i
create_db()
lMt := .f.
if !empty( par1 ) .and. lower( par1 ) = "--exclude="
cExclude := substr( par1, 11 )
par1 := par2
elseif !empty( par2 ) .and. lower( par2 ) = "--exclude="
cExclude := substr( par2, 11 )
else
cExclude := ""
endif
if lower( cExclude ) == "mem"
cExclude := "029.030.023.025.027.040.041.043.052.053.019.022.031.032"
endif
#ifdef __HARBOUR__
#include "hbmemory.ch"
if MEMORY( HB_MEM_USEDMAX ) != 0
@@ -316,14 +396,19 @@ endif
? date(), time(), os()
#ifdef __HARBOUR__
lMT := !empty( par1 ) .and. hb_mtvm()
? version() + iif( hb_mtvm(), " (MT)" + iif( lMT, "+", "" ), "" ), ;
if !hb_mtvm()
nMT := 0
endif
? version() + iif( hb_mtvm(), " (MT)" + iif( nMT != 0, "+", "" ), "" ), ;
hb_compiler()
#else
? version()
#endif
? "N_LOOPS =", N_LOOPS
? "THREADS:", iif( nMT < 0, "all->" + ltrim( str( N_TESTS ) ), ltrim( str( nMT ) ) )
? "N_LOOPS:", ltrim( str( N_LOOPS ) )
if !empty( cExclude )
? "excluded tests:", cExclude
endif
x :=t000()
? dsp_result( x, 0 )
nLoopOverHead := x[2]
@@ -334,7 +419,7 @@ nSeconds := seconds()
nTimes := secondsCPU()
#ifdef __HARBOUR__
if lMT
if nMT < 0
aThreads := array( N_TESTS )
for i:=1 to N_TESTS
cNum := strzero( i, 3 )
@@ -347,6 +432,28 @@ nTimes := secondsCPU()
? dsp_result( x, nLoopOverHead )
endif
next
elseif nMT > 0
aThreads := {}
aResults := array( N_TESTS )
mtxJobs := hb_mutexCreate()
for i:=1 to nMT
aadd( aThreads, hb_threadStart( "thTest", mtxJobs, aResults ) )
next
for i:=1 to N_TESTS
if !strzero( i, 3 ) $ cExclude
hb_mutexNotify( mtxJobs, i )
endif
next
for i:=1 to nMT
hb_mutexNotify( mtxJobs, NIL )
next
hb_threadWaitForAll()
for i:=1 to N_TESTS
if aResults[ i ] != NIL
? dsp_result( aResults[ i ], nLoopOverHead )
endif
next
mtxJobs := NIL
else
for i:=1 to N_TESTS
cNum := strzero( i, 3 )
@@ -375,7 +482,6 @@ nSeconds := seconds() - nSeconds
remove_db()
return
function f0()
return nil