Skip to content

Commit

Permalink
perf improvements for findDomainID()
Browse files Browse the repository at this point in the history
The function findDomainID() is called a lot and contains a simple test to avoid
further iteration and more expensive calls within.  This commit improves the
performance overall by optimizing the simple test to match more frequently and
perform the actual comparison quicker too.

The original code will try a quick match on the first char of the domain before
continuing, which from my testing actually appears to match more regularly
than expected, and therefor, continue with more expensive calls and further iteration.

This is because common "domains" tend to start with things like 'www.' or
'mail. or 'img.' (etc., etc.) and also the frequency of the first letters in
domains generally seems to be fairly common too.

This patch implements an approach to test whether 4 chars are the
same, offset 4 chars within the domain (to avoid 'www.' and similar), unless
the length of the domain is less than 4 chars and we revert to the original
first char only test.

The 4 chars are also packed into an int sized register for comparison which
means the comparison is just as fast as the single char test.

My testing of these two changes on my modest Pi 3 Model B Rev 2 (the 1GB RAM,
non-GbE Quad-core 1.2 GHz kind) showed an average 20% improvement in dns lookup
latency (namebench showed 103ms to 83ms improvement using Alexa Top 200
domains).

Signed-off-by: stuXORstu stuXORstu@gmail.com
  • Loading branch information
stuXORstu committed Jan 22, 2022
1 parent b197b69 commit 1f4b1c6
Showing 1 changed file with 28 additions and 5 deletions.
33 changes: 28 additions & 5 deletions src/datastructure.c
Expand Up @@ -123,19 +123,42 @@ int findDomainID(const char *domainString, const bool count)
{
for(int domainID = 0; domainID < counters->domains; domainID++)
{
// Get domain pointer
// Get domain pointer and copy of domain->domainpos
domainsData* domain = getDomain(domainID, true);
const char *localDomainPos = getstr(domain->domainpos);

// Check if the returned pointer is valid before trying to access it
if(domain == NULL)
continue;

// Quick test: Does the domain start with the same character?
if(getstr(domain->domainpos)[0] != domainString[0])
continue;
// Quick test: If the string is >=8 chars, does the domain contain 4 of
// the same chars, offset 4 chars into the string (avoiding over-matching on more frequent 'www.')
if(strlen(domainString) >= 8)
{
// Quicker test: packing the 4 chars for more efficient 'CMP eax, ecx/CMP r1, r2' comparision
int packedDomainPos, packedDomainString;
packedDomainPos = ((int)(char)localDomainPos[4] << 24)
| ((int)(char)localDomainPos[5] << 16)
| ((int)(char)localDomainPos[6] << 8)
| ((int)(char)localDomainPos[7]);
packedDomainString = ((int)(char)domainString[4] << 24)
| ((int)(char)domainString[5] << 16)
| ((int)(char)domainString[6] << 8)
| ((int)(char)domainString[7]);

if (packedDomainPos != packedDomainString)
continue;
}
else
{
// Quick test: Does the domain start with the same character?
if(localDomainPos[0] != domainString[0])
continue;
}


// If so, compare the full domain using strcmp
if(strcmp(getstr(domain->domainpos), domainString) == 0)
if(strcmp(localDomainPos, domainString) == 0)
{
if(count)
domain->count++;
Expand Down

0 comments on commit 1f4b1c6

Please sign in to comment.