diff --git a/harbour/ChangeLog b/harbour/ChangeLog index 879319d703..cabb52465d 100644 --- a/harbour/ChangeLog +++ b/harbour/ChangeLog @@ -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 diff --git a/harbour/contrib/xhb/xcstr.prg b/harbour/contrib/xhb/xcstr.prg index f20891cea8..06def005ae 100644 --- a/harbour/contrib/xhb/xcstr.prg +++ b/harbour/contrib/xhb/xcstr.prg @@ -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