Plateforme Level Extreme
Abonnement
Profil corporatif
Produits & Services
Support
Légal
English
Is scatter name loTemp slower than scatter memvar?
Message
 
 
À
15/08/2001 22:24:49
Dragan Nedeljkovich (En ligne)
Now officially retired
Zrenjanin, Serbia
Information générale
Forum:
Visual FoxPro
Catégorie:
Codage, syntaxe et commandes
Divers
Thread ID:
00544355
Message ID:
00544685
Vues:
15
Hi Dragan,

This is modified code, which runs much faster, than original. I added indexing at the end (leave only one index), I use table exclusive (it's created in the procedure, so it can be used exclusive), I changed scatter name to scatter memvar and append blank+gather replaced with insert. Resulting program works ~10 times faster. Do you think, I need to optimize it futher using your textmerge suggestion?
*--- instantiate thermometer bar class....
loTherm = newobject("thermometer", "wg.vcx","","MMR Calculation Progress for: "+m.lcOutTableFullName,m.lnTally)
loTherm.show()
local lcccTown, lnRank
k=0
do while k<3 and not m.llHalt
	k=m.k+1 && Increment count
	for i=m.lnStart to m.lnEnd step m.lnStep && Two ranking (by Num and by Vol)
		select ('curAll'+transform(m.k))
		set order to tag tag(m.i) descending && Reverse order NumAll, VolAll, NumPur, etc.
		lcccTown=ccode+town
		lnRank=0
		scan for !m.llHalt
			lnCount=m.lnCount+1

** Update status message
			if mod(m.lnCount,100) = 0
				set message to 'Record # '+transform(m.lnCount)+m.lcMsgTail
			endif

** Update thermometer
			if mod(m.lnCount,m.lnUpdateNumber) = 0
				loTherm.update(m.lnCount)
			endif

			scatter memvar && name loTemp
			lcSearchExpr=m.ccode + m.town
			if seek(m.lcSearchExpr, 'curSumAll'+transform(m.k), 'cctown')
				select ('curSumAll'+transform(m.k))
				do case
				case m.i=1 && NumAll
					lcExt='All'
					lnTotal= YtdNumAll && for all lenders in this town
					if m.lnTotal>0 && Should be always >0
						MksNumAll=round((m.YtdNumAll/m.lnTotal)*100,2)
					else
						MksNumAll=0
					endif
					release MksNumPur, RankNumPur, MksNumRef, RankNumRef, ;
						MksVolPur, RankVolPur, MksVolRef, RankVolRef, ;
						MksVolAll, RankVolAll

				case m.i=2 && VolAll
					lcExt='All'
					lnTotal= YtdVolAll && for all lenders in this town
					if m.lnTotal>0 && Should be always >0
						MksVolAll=round((m.YtdVolAll/m.lnTotal)*100,2)
					else
						MksVolAll=0
					endif
					release MksNumPur, RankNumPur, MksNumRef, RankNumRef, ;
						MksVolPur, RankVolPur, MksVolRef, RankVolRef, ;
						MksNumAll, RankNumAll


				case m.i=3 && NumPur
					lcExt='Pur'
					lnTotal=YtdNumPur && for all lenders in this town
					if m.lnTotal>0 && Should be always >0
						MksNumPur=round((m.YtdNumPur/m.lnTotal)*100,2)
					else
						MksNumPur=0
					endif
					release MksNumAll, RankNumAll, MksNumRef, RankNumRef, ;
						MksVolAll, RankVolAll, MksVolRef, RankVolRef, ;
						MksVolPur, RankVolPur


				case m.i=4 && VolPur
					lcExt='Pur'
					lnTotal=YtdVolPur && for all lenders in this town
					if m.lnTotal>0 && Should be always >0
						MksVolPur=round((m.YtdVolPur/m.lnTotal)*100,2)
					else
						MksVolPur=0
					endif
					release MksNumAll, RankNumAll, MksNumRef, RankNumRef, ;
						MksVolAll, RankVolAll, MksVolRef, RankVolRef, ;
						MksNumPur, RankNumPur

				case m.i=5 && NumRef
					lcExt='Ref'
					lnTotal=YtdNumRef && for all lenders in this town
					if m.lnTotal>0 && Should be always >0
						MksNumRef=round((m.YtdNumRef/m.lnTotal)*100,2)
					else
						MksNumRef=0
					endif
					release MksNumAll, RankNumAll, MksNumPur, RankNumPur, ;
						MksVolAll, RankVolAll, MksVolPur, RankVolPur, ;
						MksVolRef, RankVolRef


				case m.i=6 && VolRef
					lcExt='Ref'
					lnTotal=YtdVolRef && for all lenders in this town
					if m.lnTotal>0 && Should be always >0
						MksVolRef=round((m.YtdVolRef/m.lnTotal)*100,2)
					else
						MksVolRef=0
					endif
					release MksNumAll, RankNumAll, MksNumPur, RankNumPur, ;
						MksVolAll, RankVolAll, MksVolPur, RankVolPur, ;
						MksNumRef, RankNumRef

				endcase
			endif
			if left(m.lender,4)='MISC' or m.lender='SELLER'
** Nothing
			else
				lnRank=m.lnRank+1
				store m.lnRank to ('m.Rank'+iif(mod(m.i,2)=1,'Num','Vol')+ m.lcExt)
			endif
			if m.ccode+m.town<>m.lcccTown
				lcccTown= m.ccode+m.town
				if left(m.lender,4)='MISC' or m.lender='SELLER'
					lnRank=0
				else
					lnRank=1
					store m.lnRank to ('m.Rank'+iif(mod(i,2)=1,'Num','Vol')+m.lcExt)
				endif
			endif
			lcSearchExpr=m.lcSearchExpr+m.lender
			select OutTable
			if not indexseek(m.lcSearchExpr,.t.) && 'OutTable','ccttlndr')
				insert into OutTable from memvar
			else
				gather memvar && name loTemp fields ccode, town, Lender, LndrName, county, ;
*!*					city, State, ;
*!*					YtdNumAll, YtdVolAll, PtdNumAll, PtdVolAll, ;
*!*					YtdNumPur, YtdVolPur, PtdNumPur, PtdVolPur, ;
*!*					YtdNumRef, YtdVolRef, PtdNumRef, PtdVolRef, ;
*!*					&lcFieldsAdd
			endif
		endscan
	next

* Finished with curAll
	use in select('curAll'+transform(m.k))
	select ('curSumAll'+transform(m.k))
	scan for !m.llHalt
		lnCount=m.lnCount+1

** Update status message
		if mod(m.lnCount,100) = 0
			set message to 'Record # '+transform(m.lnCount)+m.lcMsgTail
		endif
** Update thermometer
		if mod(m.lnCount,m.lnUpdateNumber) = 0
			loTherm.update(m.lnCount)
		endif
		scatter memvar
		lcSearchExpr=m.ccode + m.town + m.lender
		select OutTable
		if not indexseek(m.lcSearchExpr,.t.) && 'OutTable','ccttlndr')
			insert into OutTable from memvar
		else
			gather memvar
		endif
	endscan
	use in select('curSumAll'+transform(m.k))
enddo
>>Hi everybody,
>>
>>I have a program in which I scan through quite a long file (200000 recs and more) and perform some calculations. Here is the code fragment from this program:
>>
>[snipped]
>>
>>It seems to work slow. I believe, I had scatter memvar before and it worked faster, but I'm not sure. So, do you think, it's related with scatter memvar vs. scatter name or do you see some problems in this code, which may cause slowness?
>>
>>Thanks in advance.
>
>This is about Fox's internals - as usual, you better try it on a simpler test using both versions of Scatter/Gather.
>
>The speed of a thing like this may be affected by several other things, like the number of active indexes. Things I can pull out of my bag of tricks on this:
>
>- don't append blank and gather, do a SQL insert. The first way has four writes (blank value, blank index entry (entries?), real value, update indexes)
>- if dropping indexes is not an option, then don't insert into the original table, but into a cursor with compatible structure. In the end, update from the cursor. That way the indexes in the target table are updated in a single run, not record by record.
>- finally, a thing I'm experimenting with recently (actually, first real try today): generate a .prg which will run the updates. That way you'd have code for each of the sets of variable you're dealing with, thus completely dropping the long Case statement (which is now running for each m.i). In the generated .prg you may have some tests done before the .prg is generated, so they don't have to repeat for each loop.
>...gee, I had trouble explaining this to my boss, but by the end of the day I had the skeleton of it working :).
>
>Well, something like this:
>
>local lcccTown, lnRank, lcFieldsAdd
>set text to temp.prg
>set text on
>set textmerge delim to "[[,]]"   && or so, just to make it readable here
>\lparam cFile
>for i=m.lnStart to m.lnEnd step m.lnStep
>   \select (cFile)
>   \set order to [[tag(m.i)]] desc
>   \lcccTown=ccode+town
>   \lnRank=0
>   \scan for !m.llHalt
>   \     lnCount=m.lnCount+1
>   \     scatter name loTemp
>   \     with loTemp
>   do case
>      case m.i=1
>         \           lcExt='All'
>         \           lnTotal= && for all lenders in this town
>         \           if YtdNumAll>0 && Should be always >0
>         \              .MksNumAll=round((.YtdNumAll/YtdNumAll)*100,2)
>         \           else
>         \              .MksNumAll=0
>         \           endif
>         \           lcFieldsAdd='MksNumAll, RankNumAll'
>         \           if left(.lender,4)='MISC' or .lender='SELLER'
>\** Nothing
>         \           else
>         \                lnRank=m.lnRank+1
>         \                store m.lnRank to ('loTemp.Rank'+iif(mod(m.i,2)=1,'Num','Vol')+m.lcExt)
>         \           endif
>* add the rest the same wayy
>         \      endwith
>         \      select OutTable
>         \      if not seek(m.lcSearchExpr,'OutTable','ccttlndr')
>** We're now on the right record
>         \           insert into outtable ({key field here}) value (m.lcSearchExpr)
>         \      endif
>         \      gather name loTemp fields ccode, town, Lender, LndrName, county, ;
>         \         city, State, ;
>         \         YtdNumAll, YtdVolAll, PtdNumAll, PtdVolAll, ;
>         \         YtdNumPur, YtdVolPur, PtdNumPur, PtdVolPur, ;
>         \         YtdNumRef, YtdVolRef, PtdNumRef, PtdVolRef, ;
>         \         MksNumAll, RankNumAll
>         \   endscan
>      case m.i=2
>{etc etc, just repeat this for others)
>endfor
>set text off
>set text to
>
>k=0
>
>do while k<3 and not m.llHalt
>     k=m.k+1 && Increment count
>     do temp with ('curAll'+transform(m.k))
>enddo
>
>
>Using more textmerge stuff, you may even have the few things which change with m.i in arrays in the generating/calling routine, and just merge them the way we did with the tag(m.i) here, and thus do away with the case statement.
If it's not broken, fix it until it is.


My Blog
Précédent
Suivant
Répondre
Fil
Voir

Click here to load this message in the networking platform