xsharp.eu • speed of LOCATE command in X# vs VFP - Page 4
Page 4 of 4

speed of LOCATE command in X# vs VFP

Posted: Thu Sep 17, 2020 12:03 am
by jpmoschi
hi boys
I am a XSHARP tester to migrate from VFP Applications and i agree with Loy. We can use the power of the .Net Framework to resolve X# situations but a simple loop is really important, FoxPro is 27 times faster than XSharp

I think that at least a brief look at the performance is important to give ideas to minimize the differences. Don't get me wrong, I consider tha
I'm sure csharp is the best project ever to migrate to .net from FoxPro

Below I paste the source code tested in both environments

* FOXPRO 0.4 SECONDS
*************************************************
LOCAL lalias
If Used("w03oper")
lalias= "w03operTMP"
Else
lalias= "w03oper"
Endif
sqlexec("SELECT distinct top 1000 * from m03oper" , lalias) <---- lalias has 153 columns

If Used("w03operTMP")
Zap In W03OPER
Select W03operTMP
GO top

Do While !Eof("W03operTMP") <----- performance problems begin
Scatter Name lbuff
Select W03OPER
Append Blank
Gather Name lbuff
Select W03operTMP
Skip
ENDDO <----- performance problem end

Use In W03operTMP
ENDIF

*********************************************************************************
* XSHARP 11 seconds
***************************************************************************************

If Used(w03oper)
lalias= "w03operTMP"
Else
lalias= "w03oper"
Endif
d_sql("SELECT distinct top 1000 * from m03oper" , lalias)
If Used("w03operTMP")
Zap In w03oper"
Select W03operTMP
GO top
private mcache
Do While !Eof("W03operTMP")
//Scatter Name lbuff
LBUFF = ScatterTo(mcache)
SELECT W03oper
APPEND BLANK
GatherFrom(Lbuff)
Select W03operTMP
Skip
Enddo
ENDIF

********
FUNCTION ScatterTo(mcache ref Array) AS Dictionary<STRING,USUAL>
oReturn := Dictionary<STRING,USUAL>{}
if empty(mcache)
mcache:= DBStruct()
endif
AEval(mcache, {|afield,index|;
oReturn:Add(aField[DBS_NAME], FieldGet(index));
})
RETURN oReturn
*****************************************************
FUNCTION GatherFrom(aData AS Dictionary<STRING,USUAL>) AS LOGIC
LOCAL nFld AS DWORD
LOCAL nMax AS DWORD
local actual:= alias()
foreach f as KeyValuePair<STRING,USUAL> in aData
TRY
fieldputalias(actual,f:Key,f:Value)
CATCH e as Exception
d_log ("gather error" + f:key + ":"+ transform(f:Value,""), e:ToString())
RETURN FALSE
END TRY
endfor
return true

speed of LOCATE command in X# vs VFP

Posted: Thu Sep 17, 2020 6:03 am
by Chris
Hi Juan Pablo,

Thanks for your sample! As noted earlier, this performance problem has been acknowledged and logged, it's somehting that we'll definitely look into. It's just that everything takes time, first we need to make sure we reach as much compatibility level as possible, then we can do optimizations, so it might take a bit more time to improve performance. But it will get there. Probably not at exact VFP levels (managed code always introduces some performance drop compared to native code, it's the price to pay for all the other improvements), but it will definitely get a lot better.

speed of LOCATE command in X# vs VFP

Posted: Thu Sep 17, 2020 5:59 pm
by jpmoschi
Chris, look the bottleneck in analyzer sreen capture
For me a sorprise!!!
I want to help, what poject y nead to download to analize inside

speed of LOCATE command in X# vs VFP

Posted: Thu Sep 17, 2020 9:46 pm
by Chris
Why a surprise, it makes sense that most of the time is spent in the dbf access, with the FieldGet() function.

This is where you can find the code for the runtime, including the DBF system https://github.com/X-Sharp/XSharpPublic ... re/Runtime but I think we already know that what mostly needs to be done is to add some caching of data to speed dbf access up..

speed of LOCATE command in X# vs VFP

Posted: Fri Sep 18, 2020 6:19 am
by robert
Juan,
apart from the speed issue with the DBF access this code also can be optimized:
- for every record in the loop you are asking for DbStruct(). If your table has 153 columns then this will create an array of 153 elements where each element is also an array of 4 elements. So for every record you are creating 154 arrays, where all you need is the name.
I would advise to use a simple loop from 1 to FCount() and to retrieve the fieldname with FieldName() and the value with FIeldGet(). This also means that you do not need aeval anymore.
Btw in the next build of X# (2.6) we have added support for Scatter and Gather (and append from array and copy to array).
Robert