for i = 1 to 10 > j = at( x, y, i ) >endfor>
for i = 1 to 10 > j = at( x, y ) > y = substr( y, j+1) >endfor>
#DEFINE hcSearchFor [http://] #DEFINE hnCharVarMaxLength 16777184 #DEFINE hnFillerLengthMultiplier 2 #DEFINE hnMinimumTestSeconds 2 #DEFINE hcResultsCursorName [Results] LOCAL ; lnIx * Set SETs appropriately: DO SetSets * Build the results cursor: DO BuildCursor * This test measures the speed of the AT() function on strings of varying length. * Each test string is built from a number of "filler" characters, followed by * the test string hcSearchFor. * For "easy" tests, the filler characters will be different from any character * in the test string so AT() can reject them at maximum speed. lcFiller = GetFillerString(hcSearchFor, 0) * We'll run one set of tests based on filler length of 1023 so we can get * close to the maximum allowable string length in our testing * (which is a little less than 16MB): DO RunMultiTests WITH [Easy], lcFiller, 1023 DO RunMultiTests WITH [Easy], lcFiller, 1024 * Now we make it harder - the filler string starts to look increasingly * like the string we're looking for: FOR lnIx = 1 TO LEN(hcSearchFor) - 1 STEP 1 lcFiller = GetFillerString(hcSearchFor, lnIx) DO RunMultiTests WITH [Stress], lcFiller, 1024 ENDFOR SELECT (hcResultsCursorName) GO TOP BROWSE NOWAIT RETURN * EOM() **************************************** PROCEDURE SetSets SET TALK OFF SET ESCAPE ON RETURN * EOM() **************************************** PROCEDURE BuildCursor IF USED(hcResultsCursorName) USE IN (hcResultsCursorName) ENDIF CREATE CURSOR (hcResultsCursorName) ; (cTest C(6), ; cFiller C(LEN(hcSearchFor) - 1), ; iFillerLength I, ; iTestIterations I, ; nSecondsElapsed N(7, 3), ; iFillCharsPerSec I) RETURN * EOM() **************************************** FUNCTION GetFillerString LPARAMETERS ; tcSearchFor, ; tnFillFactor LOCAL ; lcRetVal IF tnFillFactor = 0 * We want a filler string that is not present at all in the SearchFor string: lcRetVal = [A] DO WHILE lcRetVal $ tcSearchFor lcRetVal = CHR(ASC(lcRetVal) + 1) ENDDO ELSE * We want a filler string that is some substring of the SearchFor string: lcRetVal = SUBSTR(tcSearchFor, 1, tnFillFactor) ENDIF RETURN lcRetVal * EOM() **************************************** PROCEDURE RunMultiTests LPARAMETERS ; tcType, ; tcFiller, ; tnStartFillerLength LOCAL ; lnFillerLength lnFillerLength = tnStartFillerLength DO WHILE lnFillerLength + LEN(hcSearchFor) <= hnCharVarMaxLength DO RunOneTest WITH tcType, tcFiller, lnFillerLength lnFillerLength = lnFillerLength * hnFillerLengthMultiplier ENDDO RETURN * EOM() **************************************** PROCEDURE RunOneTest LPARAMETERS ; tcType, ; tcFiller, ; tnFillerLength LOCAL ; lnFillerLength, ; lnSecondsStart, ; lnSecondsElapsed, ; lnTestIterations, ; lnIx, ; lcTest * We'll round down the filler length to the nearest full multiple * of the length of the fill string: lnFillerLength = INT(tnFillerLength / LEN(tcFiller)) * LEN(tcFiller) lcTest = REPLICATE(tcFiller, lnFillerLength / LEN(tcFiller)) + hcSearchFor lnTestIterations = 1 lnSecondsStart = SECONDS() =AT(hcSearchFor, lcTest) lnSecondsElapsed = SECONDS() - lnSecondsStart DO WHILE lnSecondsElapsed < hnMinimumTestSeconds * If the elapsed time was very short try to figure out a number of test iterations * that will be close to hnMinimumTestSeconds: DO CASE CASE lnSecondsElapsed = 0 * Unmeasurably short, arbitrarily set a number of iterations: lnTestIterations = lnTestIterations * 1000 * hnMinimumTestSeconds CASE lnSecondsElapsed < 0.01 * May be under the resolution of SECONDS() on NT/W2K/XP, * multiply the calculated iterations by 150%: lnTestIterations = lnTestIterations * 1.5 * (hnMinimumTestSeconds / lnSecondsElapsed) OTHERWISE * Assume the resolution of SECONDS() is OK: lnTestIterations = lnTestIterations * hnMinimumTestSeconds / lnSecondsElapsed ENDCASE lnSecondsStart = SECONDS() FOR lnIx = 1 TO lnTestIterations STEP 1 =AT(hcSearchFor, lcTest) ENDFOR lnSecondsElapsed = SECONDS() - lnSecondsStart ENDDO * Write the results to the cursor: INSERT INTO (hcResultsCursorName) ; (cTest, ; cFiller, ; iFillerLength, ; iTestIterations, ; nSecondsElapsed, ; iFillCharsPerSec) ; VALUES ; (tcType, ; tcFiller, ; lnFillerLength, ; lnTestIterations, ; lnSecondsElapsed, ; INT(lnTestIterations * lnFillerLength / lnSecondsElapsed)) WAIT WINDOW NOWAIT [Filler String: ] + "[" + tcFiller + "]" ; + [ Fill Length: ] + LTRIM(STR(lnFillerLength)) RETURN * EOM() ****************************************