[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: A little compression...



Harry Potter schreef:
On May 24, 5:02 pm, Harry Potter <maspethro...@aol.com> wrote:
It's closed source.  Do I have another choice?  Perhaps a general
guide on the internet for optimizing C++ code?

What helps is using a profiler to identify the hotspots in your code. Are you sure that most time is spend in the functions below?


Maybe this will help:

//Compares a block at loc. Cur to loc. Prev in the input buffer c.In
and returns the length.
unsigned ByteRef::ChkBlock (unsigned Cur, unsigned Prev, compbuffer
&c)
{
	unsigned int i, j, k;
	register unsigned char* in2=c.In;
	//Get max. compare len. in j
	j=Cur-Prev;
	k=c.InLen-Cur; if (k<j) j=k;
	if (j>65) j=65;	//Max. possible ref. len. =65 bytes
	for (i=0; i<j && in2[Cur+i]==in2[Prev+i]; i++);
	if (i<3) i=0;

	return i;
}

The register keyword is unlikely to have any beneficial effect with most compilers. Instead of using array indexes in the for loop, you might consider using pointer arithmetic, whether you gain anything will depend on the compiler (untested code):

unsigned ByteRef::ChkBlock (unsigned Cur, unsigned Prev, compbuffer& c)
{
 	//Get max. compare len. in j
 	unsigned int j=Cur-Prev;
 	unsigned in k=c.InLen-Cur; if (k<j) j=k;
 	if (j>65) j=65;	//Max. possible ref. len. =65 bytes

	const unsigned char* start = c.In + Cur;
        const unsigned char* end = c.In + j;
        const unsigned char* p1 = start;
        const unsigned char* p2 = c.In + Prev;
 	for (; p1 != end && *p1 == *p2; ++p1, ++p2);

	unsigned int i = p1-start;
 	if (i<3) i=0;

 	return i;
}

You could also consider comparing 32 bit values at a time, and if the 32-bit values are unequal figure out which byte is not equal. You could also consider using SSE instructions, which can compare 16 bytes at a time and tell you which bytes are equal. However comparing multiple bytes at a time does make the code quite a bit more complex.

unsigned ByteRef::ScanRef (int pos, compbuffer &c)
{
	int i;			//Temp. variables
	int j, k;
	unsigned char *in=c.In, *cu=in+pos;	//Just to speed access.
	len=0;	//Len.=0 for init. block.
	if (c.InLen-pos<3||pos<1) return 0;
	//Scan from current p0os.-1 to beginning of input.
	for (i=pos-1;pos<=ByteRefDepth-2?i>=0:i>=pos-(ByteRefDepth-1); i--)
	{
		if (*(unsigned short*)(cu)==*(unsigned short*)(in+i) &&
			//If word at current pos.=word at compare block ==,
			(j=ChkBlock(pos,i, c))>len) {	//and better than best,
			len=j; loc=i;		//make current best.
		}
	}
	return len;
}

For C++ point of view I see little room for substantial performance improvement. Playing with the optimization settings of the compiler and/or using a more up-to-date compiler may gain some performance improvement, but it is very unlikely to gain orders of magnitude improvement. In my experience changing the algorithm is the most likely way to gain a substantial (orders of magnitude) performance improvement.

Note that non of this is topical for the groups you (and I) are posting to.