2009-08-12 00:15 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl)

* harbour/contrib/xhb/xcstr.prg
    % fixed fatal for performance code used to serialize hash arrays
      in ValToPrg() functions. I know that xHarbour does not have native
      support for hash array iteration in FOR EACH statements so it's
      necessary to make some hacks but even there serialization can be
      quite easy done by simple FOR/NEXT loop and function calls to
      access given keys and values.
      Please remember that sending :keys or :values messages to hash
      arrays is very expensive in both languages because each time
      new array is created with copy of all key or values items.
      In the old code :values message was send inside a loop so to serialize
      hash array with 1000 items it was created 1000 arrays with 1000
      items inside each of them. It means 1000000 unnecessary item copy
      calls. Modern computers are very fast but such code can kill the
      performance on any hardware. It's also classic example when forcing
      FOR EACH usage in all places can give code thousands times slower
      then code using simple FOR/NEXT.
    % few minor optimizations
This commit is contained in:
Przemyslaw Czerpak
2009-08-11 22:16:01 +00:00
parent 7055dd0667
commit 20a5e7c24b
2 changed files with 38 additions and 26 deletions

View File

@@ -17,6 +17,26 @@
past entries belonging to author(s): Viktor Szakats.
*/
2009-08-12 00:15 UTC+0200 Przemyslaw Czerpak (druzus/at/priv.onet.pl)
* harbour/contrib/xhb/xcstr.prg
% fixed fatal for performance code used to serialize hash arrays
in ValToPrg() functions. I know that xHarbour does not have native
support for hash array iteration in FOR EACH statements so it's
necessary to make some hacks but even there serialization can be
quite easy done by simple FOR/NEXT loop and function calls to
access given keys and values.
Please remember that sending :keys or :values messages to hash
arrays is very expensive in both languages because each time
new array is created with copy of all key or values items.
In the old code :values message was send inside a loop so to serialize
hash array with 1000 items it was created 1000 arrays with 1000
items inside each of them. It means 1000000 unnecessary item copy
calls. Modern computers are very fast but such code can kill the
performance on any hardware. It's also classic example when forcing
FOR EACH usage in all places can give code thousands times slower
then code using simple FOR/NEXT.
% few minor optimizations
2009-08-12 00:07 UTC+0200 Viktor Szakats (harbour.01 syenar.hu)
- tests/bldtest/bldtest.hbp
+ tests/bldtest/Makefile

View File

@@ -136,12 +136,11 @@ RETURN "[" + cString + "]"
//--------------------------------------------------------------//
FUNCTION ValToPrg( xVal, cName, nPad, aObjs )
LOCAL cType := ValType( xVal )
LOCAL aVar, cRet, cPad, nObj
//TraceLog( xVal, cName, nPad, aObjs )
SWITCH cType
SWITCH ValType( xVal )
CASE 'C'
RETURN StringToLiteral( xVal )
@@ -152,7 +151,7 @@ FUNCTION ValToPrg( xVal, cName, nPad, aObjs )
RETURN IIF( xVal, ".T.", ".F." )
CASE 'N'
RETURN Str( xVal )
RETURN hb_nToS( xVal )
CASE 'A'
IF cName == NIL
@@ -184,22 +183,23 @@ FUNCTION ValToPrg( xVal, cName, nPad, aObjs )
RETURN cRet
CASE 'H'
IF Len( xVal ) == 0
RETURN "hb_Hash()"
IF Empty( xVal )
cRet := "hb_Hash()"
ELSE
cRet := "{ "
FOR EACH aVar IN xVal:Keys
cRet += ValToPrg( aVar ) + " => "
cRet += ValToPrg( xVal:Values[ aVar:__EnumIndex() ] ) + ", "
FOR EACH aVar IN xVal
IF aVar:__enumIndex() != 1
cRet += ", "
ENDIF
cRet += ValToPrg( aVar:__enumKey() )
cRet += " => "
cRet += ValToPrg( aVar )
NEXT
/* We know for sure xVal isn't empty, and a last ',' is here */
cRet = SubStr( cRet, 1, Len( cRet ) - 2 ) + " }"
RETURN cRet
cRet += " }"
ENDIF
RETURN cRet
/* There is no support for codeblock serialization */
#if 0
CASE 'B'
@@ -286,9 +286,7 @@ RETURN LTrim( CStr( xVal ) )
//--------------------------------------------------------------//
FUNCTION ValToDate( xVal )
LOCAL cType := ValType( xVal )
SWITCH cType
SWITCH ValType( xVal )
CASE 'A'
CASE 'H'
CASE 'L'
@@ -334,9 +332,7 @@ RETURN { ValToCharacter( xVal ) => xVal }
//--------------------------------------------------------------//
FUNCTION ValToLogical( xVal )
LOCAL cType := ValType( xVal )
SWITCH cType
SWITCH ValType( xVal )
CASE 'A'
CASE 'D'
CASE 'H'
@@ -373,9 +369,7 @@ RETURN .F.
//--------------------------------------------------------------//
FUNCTION ValToNumber( xVal )
LOCAL cType := ValType( xVal )
SWITCH cType
SWITCH ValType( xVal )
CASE 'A'
CASE 'H'
RETURN Len( xVal )
@@ -413,9 +407,7 @@ RETURN 0
//--------------------------------------------------------------//
FUNCTION ValToObject( xVal )
LOCAL cType := ValType( xVal )
SWITCH cType
SWITCH ValType( xVal )
CASE 'A'
ENABLE TYPE CLASS ARRAY
EXIT