Plateforme Level Extreme
Abonnement
Profil corporatif
Produits & Services
Support
Légal
English
Can this VFP code be faster? (File Expansion)
Message
De
21/11/2005 09:13:03
 
 
À
20/11/2005 12:14:39
Information générale
Forum:
Visual FoxPro
Catégorie:
Codage, syntaxe et commandes
Versions des environnements
Visual FoxPro:
VFP 9
OS:
Windows XP SP2
Network:
Windows 2003 Server
Database:
Visual FoxPro
Divers
Thread ID:
01068953
Message ID:
01070730
Vues:
39
Thanks Christian. I have downloaded the required file and I will do some testing with this. Since once the file is uncompresses, I have to step through it again to read in the data, I may have to do another c prg to speed that portion up as well. I'll have to do some testing to see how much of a speed enhancement I can achieve for the entire process. I really appreciate your contribution!


>Hi,
>
>normally FoxPro's string handling capabilities are fast enough for most tasks, but there's at least one expection - when you have to examine a string character by character.
>
>In this situation FoxPro is "turtle slow" :). Why is that?
>
>Simple because FoxPro's string functions don't take strings as reference parameters.
>
>e.g.
>
>lcString = STRTOFILE('somefile')
>FOR xj = 1 TO LEN(lcString)
> lcChar = SUBSTR(lcString,xj,1)
> IF lcChar = 'Z'
>  && dosomething
> ENDIF
>ENDFOR
>
>
>since SUBSTR uses parameter by value semantics, the lcString variable is copied LEN(lcString) times in memory on every call to the SUBSTR function, which is of course unnecessary since lcString is never changed, but it's done anyway. so this algorithm will
>become slower proportional to the string size.
>
>So if someone is looking for REAL speed on such on algorithm .. just forget about FoxPro. C is the language to go, where you can work with pointer arithmetic on strings.
>
>your function converted to C code:
>
>#define MAX_DECOMPRESS_BUFFER	4096
>#define HEX_DIGIT(cChar)		(cChar >= 'A' ? cChar - 'A' + 11 : cChar - '0')
>void _fastcall Decompress_AL3(ParamBlk *parm)
>{
>	FCHAN hSource = -1, hDest = -1;
>	int nFileSize, nSize, nBuffSize, nCount, nErrorNo = 0, xj = 0;
>	BOOL bCallback = FALSE;
>	unsigned char *pInputBuff, *pOutputBuff, *pOutputPtr, *pInputPtr;
>	unsigned char cExpandChar;
>	VALUE(vContinue);
>	char aCallback[1024], aProgress[1024];
>
>	if (!NULLTERMINATE(p1) || !NULLTERMINATE(p2))
>		RAISEERROR(E_INSUFMEMORY);
>
>	if (PCOUNT() == 3 && !NULLTERMINATE(p3))
>		RAISEERROR(E_INSUFMEMORY);
>
>// callback function may not be longer than 768 chars
>	if (PCOUNT() == 3 && p3.ev_length >= 768)
>		RAISEERROR(E_INVALIDPARAMS);
>
>	LOCKHAND(p1);
>	LOCKHAND(p2);
>	if (PCOUNT() == 3)
>	{
>		LOCKHAND(p3);
>		// build callback command
>		strcpy(aCallback,HANDTOPTR(p3));
>		strcat(aCallback,"(%I)");
>		bCallback = TRUE;
>	}
>
>	vContinue.ev_length = TRUE;
>
>	hSource = _FOpen(HANDTOPTR(p1),FO_READONLY);
>	if (hSource == -1)
>	{
>		nErrorNo = _FError();
>		goto ErrorOut;
>	}
>
>	hDest = _FCreate(HANDTOPTR(p2),FC_NORMAL);
>	if (hDest == -1)
>	{
>		nErrorNo = _FError();
>		goto ErrorOut;
>	}
>
>	nFileSize = nSize = _FSeek(hSource,0,FS_FROMEOF);
>	_FSeek(hSource,0,FS_FROMBOF);
>
>	pInputBuff = malloc(MAX_DECOMPRESS_BUFFER);
>	pOutputBuff = malloc(MAX_DECOMPRESS_BUFFER / 4 * 256);
>	// maximum uncompressed size of MAX_DECOMPRESS_BUFFER bytes is:
>	// MAX_DECOMPRESS_BUFFER / 4 bytes (CHR(250) + 2 hexchars + chartoexpand) * maximum expansion of one char (256)
>
>	if (!pInputBuff || !pOutputBuff)
>	{
>		nErrorNo = E_INSUFMEMORY;
>		goto ErrorOut;
>	}
>
>	while (nSize)
>	{
>		if (nSize > MAX_DECOMPRESS_BUFFER)
>			nBuffSize = MAX_DECOMPRESS_BUFFER;
>		else
>			nBuffSize = nSize;
>
>		nSize -= nBuffSize;
>
>		nBuffSize = _FRead(hSource,pInputBuff,nBuffSize);
>
>		pInputPtr = pInputBuff;
>		pOutputPtr = pOutputBuff;
>		
>		while (nBuffSize--)
>		{
>			if (*pInputPtr == 250)
>			{
>				// we need the next 3 chars at least to decompress
>				if (nBuffSize >= 3)
>				{
>					pInputPtr++;
>					nCount = HEX_DIGIT(*pInputPtr) * 16;
>					pInputPtr++;
>					nCount += HEX_DIGIT(*pInputPtr);
>					pInputPtr++;
>					cExpandChar = *pInputPtr++;
>					pOutputPtr = ReplicateEx(pOutputPtr,cExpandChar,nCount);
>					nBuffSize -= 3;
>				}
>				else
>				{
>					if (nSize)
>					{
>						// special case when the buffer contains an incomplete decompression command at the end
>						// seek back to beginning of decompression command
>						nBuffSize++; // inc nBuffSize cause it contains 1 less (while (nBuffSize--))
>						_FSeek(hSource,-nBuffSize,FS_RELATIVE);
>						nSize += nBuffSize; // add the bytes to the remaining size
>						nBuffSize = 0; // set to 0 to stop while loop
>					}
>					else
>					{
>						// file contained incomplete decompression command at the end. raise some error
>						nErrorNo = E_INVALIDPARAMS;
>						goto ErrorOut;
>					}
>				}
>			}
>			else
>				*pOutputPtr++ = *pInputPtr++;
>		}
>		
>		_FWrite(hDest,pOutputBuff,pOutputPtr-pOutputBuff);
>
>		// flush after each 10th buffer
>		if (++xj % 10 == 0)
>			_FFlush(hDest);
>
>		if (bCallback)
>		{
>			sprintfex(aProgress,aCallback,nFileSize-nSize);
>			if (nErrorNo = EVALUATE(vContinue,aProgress))
>				goto ErrorOut;
>
>			if (!vContinue.ev_length)
>				break;
>		}
>	}
>
>	_FClose(hSource);
>	_FClose(hDest);
>	free(pInputBuff);
>	free(pOutputBuff);
>	UNLOCKHAND(p1);
>	UNLOCKHAND(p2);
>	if (PCOUNT() == 3)
>		UNLOCKHAND(p3);
>	RET_LOGICAL(vContinue.ev_length);
>	return;
>
>	ErrorOut:
>		UNLOCKHAND(p1);
>		UNLOCKHAND(p2);
>		if (PCOUNT() == 3)
>			UNLOCKHAND(p3);
>		if (hSource != -1)
>			_FClose(hSource);
>		if (hDest != -1)
>			_FClose(hDest);
>		if (pInputBuff)
>			free(pInputBuff);
>		if (pOutputBuff)
>			free(pOutputBuff);
>		RAISEERROR(nErrorNo);
>}
>
>char * _stdcall ReplicateEx(char *pBuffer, char pExpr, int nCount)
>{
>	while (nCount--)
>		*pBuffer++ = pExpr;
>	return pBuffer;
>}
>
>
>to make this code work you'll need the file "vfpmacros.h" from download #28338 since it uses many C macros defined in that file to make the code more readable.
>
>Regards
>Christian
.·*´¨)
.·`TCH
(..·*

010000110101001101101000011000010111001001110000010011110111001001000010011101010111001101110100
"When the debate is lost, slander becomes the tool of the loser." - Socrates
Vita contingit, Vive cum eo. (Life Happens, Live With it.)
"Life is not measured by the number of breaths we take, but by the moments that take our breath away." -- author unknown
"De omnibus dubitandum"
Précédent
Répondre
Fil
Voir

Click here to load this message in the networking platform