faster treatments in UDP connecion

Anything beyond the basics in using the LiveCode language. Share your handlers, functions and magic here.

Moderators: FourthWorld, heatherlaine, Klaus, kevinmiller, robinmiller

Post Reply
tal
Posts: 84
Joined: Thu Jul 02, 2009 3:27 pm

faster treatments in UDP connecion

Post by tal » Mon Oct 26, 2009 2:58 pm

Hi,

My revolution application is connected to another application, every 0.25 seconds the application sends 800 values to my revolution application, which must treat them very quickly, but it seems that 800 values is too much, it works with 300 values but is it very slow and sometimes the connection stops...
Have you got a solution to make revolution faster treatments?

thank you

hliljegren
Posts: 111
Joined: Sun Aug 23, 2009 7:48 am
Contact:

Post by hliljegren » Mon Oct 26, 2009 5:33 pm

It's hard to give any advice if we don't know what you are doing with the data, how big your data is. It can be revolution, your code or even your network connection. 800 values x 4 times a second x the size of your data might exceed your network speed.

800 values sent as separate packages will also cause quite an overhead. So how are you sending your data? What do you do with it when it arrives?

    tal
    Posts: 84
    Joined: Thu Jul 02, 2009 3:27 pm

    Post by tal » Tue Oct 27, 2009 10:54 am

    Hi,

    It is for an enterprise application to make a simulation.

    There is a part of my reception code :

    on webc pHost, pMsg, pSocket

    set the itemdelimiter to tab
    ----Réception de n octets
    put (chartonum(char 1 of pMsg) * 2^24 + chartonum(char 2 of pMsg )* 2^16 + chartonum(char 3 of pMsg) * 2^8 + chartonum(char 4 of pMsg)) into n

    ----Récupération des singles----
    put 12 into compteur
    lock screen
    repeat until compteur = n
    put getfloatBE(binaryencode("M*",(chartonum(char 1+compteur of pMsg) * 2^24 + chartonum(char 2+compteur of pMsg )* 2^16 + chartonum(char 3+compteur of pMsg) * 2^8 + chartonum(char 4+compteur of pMsg)))) into the item compteuritem of line 2 of fld "simu2"
    put compteur+4 into compteur
    put compteuritem+1 into compteuritem
    end repeat

    ........

    unclock screen
    end webc

    I recieve numbers, I must decode them ( because revolution interprets it as ASCII) and after I put them into a field "simu2".


    It works with 300 numbers sent but very slowly and it works perfectly with 40 numbers to 100 numbers.

    Thanks

    Mark
    Livecode Opensource Backer
    Livecode Opensource Backer
    Posts: 5150
    Joined: Thu Feb 23, 2006 9:24 pm
    Contact:

    Post by Mark » Tue Oct 27, 2009 11:55 am

    tal,

    Can you also post the getfloatBE function?

    Best regards,

    Mark
    The biggest LiveCode group on Facebook: https://www.facebook.com/groups/livecode.developers
    The book "Programming LiveCode for the Real Beginner"! Get it here! http://tinyurl.com/book-livecode

    tal
    Posts: 84
    Joined: Thu Jul 02, 2009 3:27 pm

    Post by tal » Tue Oct 27, 2009 12:43 pm

    getfloatBE is a function from a library i found in this forum (libinconvert)



    function getFloatBE pBytes
    local tNum
    if not sBigEndian then put reverseBytes(pBytes) into pBytes

    switch length(pBytes)
    case 4
    put "f" into bdc
    break
    case 8
    put "d" into bdc
    break
    case 10
    put "d" into bdc
    if not sBigEndian then put reverseBytes(pBytes) into pBytes
    put ieeeExtendedToDouble(pBytes) into pBytes
    if not sBigEndian then put reverseBytes(pBytes) into pBytes
    break
    default
    return empty
    break
    end switch

    get binarydecode(bdc, pBytes, tNum)
    return tNum
    end getFloatBE

    Thanks

    Mark
    Livecode Opensource Backer
    Livecode Opensource Backer
    Posts: 5150
    Joined: Thu Feb 23, 2006 9:24 pm
    Contact:

    Post by Mark » Tue Oct 27, 2009 2:03 pm

    tal,

    The following should be a little faster. You may have to look at the code and make a few corrections, as I can't test it here.

    Unfortunately, switching the endian is probably time consuming (you might want to post the script of that as well). I can very well imagine that handling 800 values takes more than 250 milliseconds. Hence, the only solution to run the script sufficiently quick might be to rewrite and compile it as an external.

    Code: Select all

    on webc pHost, pMsg, pSocket
         set the itemdelimiter to tab
         ----Réception de n octets
         put (chartonum(char 1 of pMsg) * 2^24 + chartonum(char 2 of pMsg )* 2^16 + \
                chartonum(char 3 of pMsg) * 2^8 + chartonum(char 4 of pMsg)) into n
         ----Récupération des singles----
         put 12 into compteur
         put empty into compteurList
         // or the following line:
         // put comma into item x of compteurList
         // if you want to start at item x+1
         repeat with compteur = 12 to n step 4
              put getfloatBE(binaryencode("M*",(chartonum(char 1+compteur of pMsg) * 2^24 + \
                     chartonum(char 2+compteur of pMsg )* 2^16 + \
                     chartonum(char 3+compteur of pMsg) * 2^8 + chartonum(char 4+compteur of pMsg)))) \
                     & comma after compteurList
         end repeat
         put compteurList into line 2 of fld "simu2"     
    end webc 
    
    
    function getFloatBE pBytes
         local tNum
         switch length(pBytes)
              case 4
                   if not sBigEndian then put reverseBytes(pBytes) into pBytes
                   put "f" into bdc
                   break
              case 8
                   if not sBigEndian then put reverseBytes(pBytes) into pBytes
                   put "d" into bdc
                   break
              case 10
                   put "d" into bdc
                   if not sBigEndian then
                        // apparently, ieeeExtendedToDouble works with big endian only
                        put reverseBytes(ieeeExtendedToDouble(pBytes)) into pBytes
                   else
                        put ieeeExtendedToDouble(pBytes) into pBytes
                   end if
                   break
              default
                   return empty
                   break
         end switch
         get binarydecode(bdc, pBytes, tNum)
         return tNum
    end getFloatBE 
    Best,

    Mark
    The biggest LiveCode group on Facebook: https://www.facebook.com/groups/livecode.developers
    The book "Programming LiveCode for the Real Beginner"! Get it here! http://tinyurl.com/book-livecode

    tal
    Posts: 84
    Joined: Thu Jul 02, 2009 3:27 pm

    Post by tal » Tue Oct 27, 2009 2:19 pm

    Thank you, it is in fact faster, i also put my data into a variable and not a field, so it makes it every 0.25 seconds now.

    Best regards

    bn
    VIP Livecode Opensource Backer
    VIP Livecode Opensource Backer
    Posts: 4163
    Joined: Sun Jan 07, 2007 9:12 pm

    Post by bn » Tue Oct 27, 2009 2:21 pm

    tal,

    a little bit of speed increase might be to call the functions as privat function. If you call a function often enough the call does not have to pass the message hierachy but stays in the script that calls the function. That means you have to move the lib into the script that calls the function.
    The syntax is to say

    Code: Select all

    private function getFloatBE pBytes 
    instead of

    Code: Select all

    function getFloatBE pBytes 
    the same goes for "reverseBytes(pBytes)" and "ieeeExtendedToDouble(pBytes)" move those functions into the script that calls the functions and prepend private.
    For a command you would say "private command myCommand" instead of "on myCommand".
    I think Mark showed the most important speed increases by putting everything inside the repeat loop into a variable "compteurList" and by appending instead of putting into item x of. If I got you right you wanted a tab as an itemdelimiter, you would have to change that in Mark's script from comma to tab.

    regards
    Bernd

    Mark Smith
    Posts: 179
    Joined: Sat Apr 08, 2006 11:08 pm
    Contact:

    Post by Mark Smith » Wed Oct 28, 2009 1:04 pm

    As the author of libBinConvert I just benchmarked the getFloatBE() function.

    For 1000 calls it took 20 - 25 millisecs on my two year old intel mac, so shouldn't be causing a problem in a 250 millisecond window...

    Also, the library was written before we had private functions, but I doubt the speed difference would be at all noticeable until you're measuring tens of thousands of iteration or more. In my 1000 iteration test, I tried making the reverseBytes() function private and it made no difference at all.

    Best,

    Mark Smith

    bn
    VIP Livecode Opensource Backer
    VIP Livecode Opensource Backer
    Posts: 4163
    Joined: Sun Jan 07, 2007 9:12 pm

    Post by bn » Wed Oct 28, 2009 1:53 pm

    Hi Mark,

    as you say you would have to call a function many, many times before the speed difference would be apparent with private instead of the usual call. According to your benchmark there is no timing problem there.
    But if you do call a function or a command often enough like in handling imagedata you will see a noticeable speed increase.
    A while ago on the list Bill Mariott had a challenge to compare two images to find out whether one or more of the pixels had changed.
    http://www.nabble.com/Inefficient-code- ... 58i20.html
    There was a one recursive algorithm by Jerry Jensen which was a couple of hundred milliseconds faster by just making the handler private, of course depending on the size of the images.
    So by all means to make a handler private is not a cure all for speed problems, but when you try to squeeze out a few milliseconds it might help.
    regards
    Bernd

    Mark Smith
    Posts: 179
    Joined: Sat Apr 08, 2006 11:08 pm
    Contact:

    Post by Mark Smith » Wed Oct 28, 2009 3:58 pm

    Bernd, you're absolutely correct. These differences are very small, but can really accumulate.

    In my Sha functions, even quite small inputs can result in millions of iterations in the inner loops. I found it made a worthwhile difference to use literals instead of constants, and to put functions 'inline', both things that would make no worthwhile difference in most circumstances.

    Best,

    Mark

    Post Reply