8
\$\begingroup\$

This journey started with a quest to create the shortest possible case-insensitive verification number. Based on the answers there, I worked out a Classic ASP/VBScript implementation of Crockford's Base32 Encoding and it has served me well so far.

Out of semi-idle curiosity, I was wondering if there was a way to further improve the performance. To be clear: it works, and it runs more than fast enough. I am planning to use it more extensively and since I never heard back on a better way, I was hoping for a second set of eyes to say "yes, it's as good as it's going to get" or "here's how to make it more awesome" or whatever.

So you don't have to go back to the latter Stack Overflow question to see the code, here it is:

'Base32 encoding functions for shorter, less confusing verification numbers
Const kBase32Digits = "0123456789abcdefghjkmnpqrstvwxyz"

Function ToBase32(ByVal lInput)
    Dim lModulo, sTemp
    Do Until lInput = 0
        lModulo = lInput Mod 32
        sTemp = Mid(kBase32Digits, lModulo + 1, 1) & sTemp
        lInput = lInput \ 32
    Loop
    ToBase32 = sTemp
End Function

Function FromBase32(ByVal sInput)
    Dim sTemp, sR, i,iY,lLen, zMultiplier
    sTemp = LCase(sInput)
    sTemp = Replace(sTemp,"o","0")
    sTemp = Replace(sTemp,"i","1")
    sTemp = Replace(sTemp,"l","1")
    sTemp = Replace(sTemp,"u","v")
    zMultiplier = 1
    lLen = Len(sTemp)
    For i = lLen To 1 Step -1
        sR = Mid(sTemp, i, 1)
        iY = InStr(1, kBase32Digits, sR, vbTextCompare) - 1
        FromBase32 = FromBase32 + iY * zMultiplier
        zMultiplier = zMultiplier * 32
    Next
End Function
\$\endgroup\$
5
\$\begingroup\$

If you really want to chase those milliseconds then I would try following:

1) I consider division operations as slow so I would avoid using two divisions if it can be replaced with one division and some easier operation:

Function ToBase32(ByVal lInput)
    Dim lModulo, sTemp, lNextInput
    Do Until lInput = 0
        lNextInput = lInput \ 32
        lModulo = lInput - 32 * lNextInput
        sTemp = Mid(kBase32Digits, lModulo + 1, 1) & sTemp
        lInput = lNextInput
    Loop
    ToBase32 = sTemp
End Function

2) In some other language I would use bit shift of course instead of diviosion/multiply. But as far as I got vbscript doesn't have bit shifting operators.

3) Your FromBase32 method doesn't look optimal to me at all. I would replace those Replace and InStr calls with array of integers for letter chars. This array will contains corresponding base 32 numbers for chars. And you will be able to translate letter into number using array indexing accessor which is much faster operation than looking for a character in a string. Some pseudocode showing how to convert character sR into number:

Dim sR;

// defining an array:
Dim charArray = [  10, // 'a' char
                   11, // 'b' char
                   ...
                   17, // 'h'
                   1 , // 'i' !! 
                   ...
                   0 , // 'o'
                   ...];

Dim lNumber;
if (sR >= 'a' && sR <= 'z')
    lNumber = charArray[sR - 'a'];
else // it is digit
    lNumber = sR - '0'  // in most languages I know this will convert '1' char into 1 integer

P.S. of course I haven't measured anything, I do not even know vbscript, just wanted to give you an idea on what can be changed.

P.P.S.: My second point doesn't take into account that there is a chance that VBScript interpreter will do such an optimization for you.

\$\endgroup\$
0
\$\begingroup\$

In the FromBase32 function, don't use vbTextCompare in your call to InStr. You've already LCase'd the string, so you're just wasting cycles by doing a text comparison.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.