sscanf vs strtok & strrest
#1

Here are the proper tests and results:

http://forum.sa-mp.com/showpost.php?...8&postcount=11
Reply
#2

Well we all now, sscanf is faster, I did actually expected even lower timing for sscanf, but this is really cool

Edit: could you also test, the speeding for loading stuff from mysql in an enum, with sscanf, explode, split, and fetching every row. I really want to know it, but not that boored to test it out :P
Reply
#3

Sorry, you'll have to do that yourself
Reply
#4

Quote:
Originally Posted by Lenny the Cup
Посмотреть сообщение
Sorry, you'll have to do that yourself
Haha :P, anyway nice job
Reply
#5

edit: Didn't see your post ******

I ran a new test to see how big the difference was between the two in three different situations:
1: Just a number (strtok(strval) vs "d")
2: A number and a name (strtok(strval) + strtok vs "du")
3: A number, a user AND the string (strtok(strval) + strtok + strrest vs "dus[24]")

Here is the script, same string as before:
pawn Код:
main()
{
    new TickStart,
        idx,
        szPlayer[MAX_PLAYER_NAME],
        iCashAmount,
        szEmote[80];
    ////////////////////////////////////////////////////////////////////////////
    TickStart = GetTickCount();
    for(new i; i < 100000; i++)
    {
        iCashAmount = strval(strtok(TESTSTRING, idx));
    }
    printf("RESULT 1 strtok & strrest: %d ticks.", GetTickCount() - TickStart);
    TickStart = GetTickCount();
    for(new i; i < 100000; i++)
    {
        sscanf(TESTSTRING, "d", iCashAmount);
    }
    printf("RESULT 1 sscanf: %d ticks.", GetTickCount() - TickStart);
    ////////////////////////////////////////////////////////////////////////////
    TickStart = GetTickCount();
    for(new i; i < 100000; i++)
    {
        iCashAmount = strval(strtok(TESTSTRING, idx));
        format(szPlayer, MAX_PLAYER_NAME, strtok(TESTSTRING, idx));
    }
    printf("RESULT 2 strtok & strrest: %d ticks.", GetTickCount() - TickStart);
   
    TickStart = GetTickCount();
    for(new i; i < 10000; i++)
    {
        sscanf(TESTSTRING, "du", iCashAmount, szPlayer);
    }
    printf("RESULT 2 sscanf: %d ticks.", GetTickCount() - TickStart);
    ////////////////////////////////////////////////////////////////////////////
    TickStart = GetTickCount();
    for(new i; i < 100000; i++)
    {
        iCashAmount = strval(strtok(TESTSTRING, idx));
        format(szPlayer, MAX_PLAYER_NAME, strtok(TESTSTRING, idx));
        format(szEmote, 80, strrest(TESTSTRING, idx));
    }
    printf("RESULT 3 strtok & strrest: %d ticks.", GetTickCount() - TickStart);
    TickStart = GetTickCount();
    for(new i; i < 100000; i++)
    {
        sscanf(TESTSTRING, "dus[80]", iCashAmount, szPlayer, szEmote);
    }
    printf("RESULT 3 sscanf: %d ticks.", GetTickCount() - TickStart);
}
And here are the results:
Код:
[18:03:41] RESULT 1 strtok & strrest: 68 ticks.
[18:03:41] RESULT 1 sscanf: 47 ticks.
[18:03:41] RESULT 2 strtok & strrest: 141 ticks.
[18:03:41] RESULT 2 sscanf: 28 ticks.
[18:03:41] RESULT 3 strtok & strrest: 382 ticks.
[18:03:42] RESULT 3 sscanf: 417 ticks.
NOTE: INVALID TEST, SEE LATER TESTS
Reply
#6

I ran a new test:

pawn Код:
stock Test2()
{
    new TickStart,
        String[80],
        idx;
    TickStart = GetTickCount();
    for(new i; i < 100000; i++)
    {
        format(String, 80, strrest(TESTSTRING, idx));
    }
    printf("RESULT strtok & strrest: %d ticks.", GetTickCount() - TickStart);
    TickStart = GetTickCount();
    for(new i; i < 100000; i++)
    {
        sscanf(TESTSTRING, "s[80]", String);
    }
    printf("RESULT sscanf: %d ticks.", GetTickCount() - TickStart);
}
Код:
[18:30:21] RESULT strtok & strrest: 120 ticks.
[18:30:21] RESULT sscanf: 134 ticks.
So apparently sscanf reads strings slightly slower than strrest (The version ****** presented).




Edit:
But on the other hand, integers are quicker:
pawn Код:
stock Test3()
{
    new TickStart,
        Integer,
        idx;
    TickStart = GetTickCount();
    for(new i; i < 1000000; i++)
    {
        Integer = strval(strtok(TESTSTRING, idx));
    }
    printf("RESULT strtok & strrest: %d ticks.", GetTickCount() - TickStart);
    TickStart = GetTickCount();
    for(new i; i < 1000000; i++)
    {
        sscanf(TESTSTRING, "i", Integer);
    }
    printf("RESULT sscanf: %d ticks.", GetTickCount() - TickStart);
}
Код:
[18:34:04] RESULT strtok & strrest: 663 ticks.
[18:34:04] RESULT sscanf: 467 ticks.
NOTE: INVALID TEST, SEE LATER TESTS
Reply
#7

pawn Код:
new
    idx;

    for(new i; i < 1000000; i++)
    {
        Integer = strval(strtok(TESTSTRING, idx));
    }
Look at where idx was defined and look at the loop:

idx is passed as a reference parameter to strtok, meaning that after your first call to strtok it will search from a different place; whereas on the other hand sscanf is still searching from the beginning. You'd probably find after x or so loops that strtok is not getting the value you're expecting, you should reset idx to 0 after each iteration.

Is this a fair test or have I missed something?
Reply
#8

If you aren't using sscanf you're far behind the curve. It is a travesty that strtok is still listed on the wiki.
Reply
#9

Quote:
Originally Posted by Simon
Посмотреть сообщение
pawn Код:
new
    idx;

    for(new i; i < 1000000; i++)
    {
        Integer = strval(strtok(TESTSTRING, idx));
    }
Look at where idx was defined and look at the loop:

idx is passed as a reference parameter to strtok, meaning that after your first call to strtok it will search from a different place; whereas on the other hand sscanf is still searching from the beginning. You'd probably find after x or so loops that strtok is not getting the value you're expecting, you should reset idx to 0 after each iteration.

Is this a fair test or have I missed something?
That's very true, good job noticing! I'll run a new test to see what the result should be.

Edit: The difference was staggering!
Here is the new code I've used (Notice i = 0; inside the loop)
pawn Код:
stock Test3()
{
    new TickStart,
        Integer,
        idx;
    TickStart = GetTickCount();
    for(new i; i < 1000000; i++)
    {
        idx = 0;
        Integer = strval(strtok(TESTSTRING, idx));
    }
    printf("RESULT strtok & strrest: %d ticks.", GetTickCount() - TickStart);
    TickStart = GetTickCount();
    for(new i; i < 1000000; i++)
    {
        sscanf(TESTSTRING, "i", Integer);
    }
    printf("RESULT sscanf: %d ticks.", GetTickCount() - TickStart);
}
And here is the very different result:
Код:
[19:33:58] RESULT strtok & strrest: 2266 ticks.
[19:33:58] RESULT sscanf: 465 ticks.
Reply
#10

Here are the new versions with the proper reset of idx inside the loop:
pawn Код:
stock Test1()
{
    new TickStart,
        idx,
        szPlayer[MAX_PLAYER_NAME],
        iCashAmount,
        szEmote[80];
    ////////////////////////////////////////////////////////////////////////////
    TickStart = GetTickCount();
    for(new i; i < 100000; i++)
    {
        idx = 0;
        iCashAmount = strval(strtok(TESTSTRING, idx));
    }
    printf("RESULT 1 strtok & strrest: %d ticks.", GetTickCount() - TickStart);
    TickStart = GetTickCount();
    for(new i; i < 100000; i++)
    {
        sscanf(TESTSTRING, "d", iCashAmount);
    }
    printf("RESULT 1 sscanf: %d ticks.", GetTickCount() - TickStart);
    ////////////////////////////////////////////////////////////////////////////
    TickStart = GetTickCount();
    for(new i; i < 100000; i++)
    {
        idx = 0;
        iCashAmount = strval(strtok(TESTSTRING, idx));
        format(szPlayer, MAX_PLAYER_NAME, strtok(TESTSTRING, idx));
    }
    printf("RESULT 2 strtok & strrest: %d ticks.", GetTickCount() - TickStart);

    TickStart = GetTickCount();
    for(new i; i < 10000; i++)
    {
        sscanf(TESTSTRING, "du", iCashAmount, szPlayer);
    }
    printf("RESULT 2 sscanf: %d ticks.", GetTickCount() - TickStart);
    ////////////////////////////////////////////////////////////////////////////
    TickStart = GetTickCount();
    for(new i; i < 100000; i++)
    {
        idx = 0;
        iCashAmount = strval(strtok(TESTSTRING, idx));
        format(szPlayer, MAX_PLAYER_NAME, strtok(TESTSTRING, idx));
        format(szEmote, 80, strrest(TESTSTRING, idx));
    }
    printf("RESULT 3 strtok & strrest: %d ticks.", GetTickCount() - TickStart);
    TickStart = GetTickCount();
    for(new i; i < 100000; i++)
    {
        sscanf(TESTSTRING, "dus[80]", iCashAmount, szPlayer, szEmote);
    }
    printf("RESULT 3 sscanf: %d ticks.", GetTickCount() - TickStart);
}

stock Test2()
{
    new TickStart,
        String[80],
        idx;
    TickStart = GetTickCount();
    for(new i; i < 100000; i++)
    {
        idx = 0;
        format(String, 80, strrest(TESTSTRING, idx));
    }
    printf("RESULT strtok & strrest: %d ticks.", GetTickCount() - TickStart);
    TickStart = GetTickCount();
    for(new i; i < 100000; i++)
    {
        sscanf(TESTSTRING, "s[80]", String);
    }
    printf("RESULT sscanf: %d ticks.", GetTickCount() - TickStart);
}
And here are the proper results:
Test 1:
Код:
[19:37:39] RESULT 1 strtok & strrest: 226 ticks.
[19:37:39] RESULT 1 sscanf: 47 ticks.
[19:37:39] RESULT 2 strtok & strrest: 767 ticks.
[19:37:40] RESULT 2 sscanf: 28 ticks.
[19:37:40] RESULT 3 strtok & strrest: 861 ticks.
[19:37:41] RESULT 3 sscanf: 345 ticks.
Test 2:
Код:
[19:37:41] RESULT strtok & strrest: 106 ticks.
[19:37:41] RESULT sscanf: 126 ticks.
Reply


Forum Jump:


Users browsing this thread: 1 Guest(s)