llSetLinkPrimitiveParamsFast is slower than expected

Creating scripts
User avatar
Saros Eclipse
Posts: 9
Joined: Tue Aug 09, 2016 11:46 pm
Location: Lynnwood, WA
Has thanked: 1 time
Been thanked: 4 times

llSetLinkPrimitiveParamsFast is slower than expected

Post by Saros Eclipse »

Hi, I'm new to Kitely but not new to scripting. I have an object rotation script that uses llSetLinkPrimitiveParamsFast, but behaves as if it's sleeping between calls. This is my actual code:

rotation newRotation = llEuler2Rot(<x, y, z> * DEG_TO_RAD);
newRotation = newRotation * base_rot;
llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_ROTATION, newRotation]);

I set the timer for 32 updates per second, but I'm only seeing 4 or 5 per second. I would expect that if I were using llSetPrimitiveParams or llSetLinkPrimitiveParams, but I'm using the fast one.

Is this a known problem, or is there a workaround?
Thanks,
Saros
mostly harmless.
User avatar
Ilan Tochner
Posts: 6518
Joined: Sun Dec 23, 2012 8:44 am
Has thanked: 4972 times
Been thanked: 4469 times
Contact:

Re: llSetLinkPrimitiveParamsFast is slower than expected

Post by Ilan Tochner »

Hi Saros,

What is the CPU usage of your world after it has finished starting up? See: https://kitely.atlassian.net/wiki/displ ... erformance

Have you tried a simple test of just moving a cube back and forth with llSetLinkPrimitiveParamsFast and seeing how often that is updated?
User avatar
Saros Eclipse
Posts: 9
Joined: Tue Aug 09, 2016 11:46 pm
Location: Lynnwood, WA
Has thanked: 1 time
Been thanked: 4 times

Re: llSetLinkPrimitiveParamsFast is slower than expected

Post by Saros Eclipse »

Hi Ilan,

The CPU graph is hugging the line at 0, and so are Packets Received and Packets Resent. Packets Sent is under 10%.

Using Top Scripts in region debug, the top five mover scripts are 5, 5, 5, 4 and 4 ms for a total of 23 ms. The world is brand new (evergreen island model) and this is the first thing I've tried building in it.

There are only a small handful of scripts, some of which are idling watching for movement (which never happens unless the anchor object is dragged). The others are listening for messages shouted by the anchors, and meanwhile animating in the timer() function.
mostly harmless.
User avatar
Handy Low
Posts: 231
Joined: Fri Nov 08, 2013 3:38 pm
Location: Yorkshire, England
Has thanked: 207 times
Been thanked: 140 times
Contact:

Re: llSetLinkPrimitiveParamsFast is slower than expected

Post by Handy Low »

Saros Eclipse wrote:I set the timer for 32 updates per second
You mean using llSetTimerEvent? You can only have 0.5s timers in OpenSim, no faster.
Handy Low
User avatar
Saros Eclipse
Posts: 9
Joined: Tue Aug 09, 2016 11:46 pm
Location: Lynnwood, WA
Has thanked: 1 time
Been thanked: 4 times

Re: llSetLinkPrimitiveParamsFast is slower than expected

Post by Saros Eclipse »

You mean using llSetTimerEvent? You can only have 0.5s timers in OpenSim, no faster.
I guess that would do it. Then how can I run any animation that updates faster than two times a second?
mostly harmless.
User avatar
Saros Eclipse
Posts: 9
Joined: Tue Aug 09, 2016 11:46 pm
Location: Lynnwood, WA
Has thanked: 1 time
Been thanked: 4 times

Re: llSetLinkPrimitiveParamsFast is slower than expected

Post by Saros Eclipse »

Ilan Tochner wrote:Have you tried a simple test of just moving a cube back and forth with llSetLinkPrimitiveParamsFast and seeing how often that is updated?
I've been reading the OS LSL wiki and trying various things that seem like they might help. It doesn't say so explicitly, but I suspect llGetPos(), llGetRot() and llGetPrimitiveParams() should be added to your list of things that cause sleep. I tried replacing these with llGetLinkPrimitiveParams() just to be safe, but it didn't improve things noticeably. It makes the scripts more self consistent though, so I'm keeping it.

The best I can do is getting the five scripts down to 17-20 ms. The remaining anchor scripts (about a dozen) consume less than 1 ms total.
mostly harmless.
User avatar
Saros Eclipse
Posts: 9
Joined: Tue Aug 09, 2016 11:46 pm
Location: Lynnwood, WA
Has thanked: 1 time
Been thanked: 4 times

Re: llSetLinkPrimitiveParamsFast is slower than expected

Post by Saros Eclipse »

FYI here are my actual scripts. These are a way to attach animated objects to each other hierarchically and animate them synchronously without inter-object communication, using the sim time clock.

Linked Anchor senses when it's been moved, and broadcasts its new position and rotation. This script is put into a child prim, and another linked object will listen for messages from it:

Code: Select all

integer  say_chan = -42432;
vector   base_pos = <0,0,0>;
rotation base_rot = <0,0,0,0>;

string FormatDecimal(float number, integer precision)
{    
    float roundingValue = llPow(10, -precision)*0.5;
    float rounded;
    if (number < 0) rounded = number - roundingValue;
    else            rounded = number + roundingValue;
 
    if (precision < 1) // Rounding integer value
    {
        integer intRounding = (integer)llPow(10, -precision);
        rounded = (integer)rounded/intRounding*intRounding;
        precision = -1; // Don't truncate integer value
    }
 
    string strNumber = (string)rounded;
    return llGetSubString(strNumber, 0, llSubStringIndex(strNumber, ".") + precision);
}

default
{
    state_entry()
    {
        llSetTimerEvent(1.0);
    }

    timer()
    {
        list        params = llGetLinkPrimitiveParams( LINK_THIS, [PRIM_POSITION, PRIM_ROTATION]);
        vector      new_pos = llList2Vector( params, 0 );
        rotation    new_rot = llList2Rot( params, 1 );
        integer     go = 0;
        if (base_pos != new_pos) {
            base_pos = new_pos;
            go = 1;
        }
        if (base_rot != new_rot) {
            base_rot = new_rot;
            go = 1;
        }
        if (go) {
            vector euler_rot = llRot2Euler(base_rot) * RAD_TO_DEG;
            llShout( say_chan, "position " + FormatDecimal(base_pos.x,2) + " " + FormatDecimal(base_pos.y,2) + " " + FormatDecimal(base_pos.z,2) + " rotation " + FormatDecimal(euler_rot.x,2) + " " + FormatDecimal(euler_rot.y,2) + " " + FormatDecimal(euler_rot.z,2));
        }
    }
}
Linked Static simply moves its object to the new position and rotation that it receives in a message from the anchor. It listens for the object according to channel and the name of the anchor child prim:

Code: Select all

string  obj_name    = "Anchor Pivot";
integer listen_chan = -42432;
integer listen_handle;

default
{
    state_entry()
    {
        listen_handle = llListen( listen_chan, obj_name, "", "" );
    }
    
    listen( integer channel, string name, key id, string message )
    {
        list values = llParseString2List( message, [" "], [] );
        if ((llList2String(values,0) == "position") && (llList2String(values,4) == "rotation")) {
            vector new_pos = <  llList2Float(values,1),
                                llList2Float(values,2),
                                llList2Float(values,3) >;
            llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_POSITION, new_pos]);
            vector new_rot = <  llList2Float(values,5),
                                llList2Float(values,6),
                                llList2Float(values,7) >;
            llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_ROTATION, llEuler2Rot(new_rot * DEG_TO_RAD)]);
        }
    }
}
Linked Driveshaft Rotation is an example of an animation script that repositions itself according to messages from its anchor. The motion is automatically in sync with other animated objects by virtue of using llGetTimeOfDay(), which is the same for every object in the world.

The constants at the top of the script control the object's relative rotation, range of movement, phase offset and time for a complete animation cycle:

Code: Select all

string  obj_name    = "Anchor Driveshaft";
integer listen_chan = -42432;
float   update_rate = 24.0;
float   cycle_time  = -24.0;
float   range       = 8.0;
float   x_rotation  = 0.0;
float   y_rotation  = 0.0;
float   z_rotation  = -106.0;
float   offset      = 0.0;
rotation base_rot   = <0,0,0,0>;
integer listen_handle;

default
{
    state_entry()
    {
        list params = llGetLinkPrimitiveParams( LINK_THIS, [PRIM_ROTATION]);
        base_rot = llList2Rot( params, 0 );
        listen_handle = llListen( listen_chan, obj_name, "", "" );
        llSetTimerEvent(1.0/update_rate);
    }
    
    listen( integer channel, string name, key id, string message )
    {
        list values = llParseString2List( message, [" "], [] );
        if ((llList2String(values,0) == "position") && (llList2String(values,4) == "rotation")) {
            vector new_pos = <  llList2Float(values,1),
                                llList2Float(values,2),
                                llList2Float(values,3) >;
            llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_POSITION, new_pos]);
            vector new_rot = <  llList2Float(values,5),
                                llList2Float(values,6),
                                llList2Float(values,7) >;
            base_rot = llEuler2Rot(new_rot * DEG_TO_RAD);
        }
    }

    timer()
    {
        float newAngle = llGetTimeOfDay() * 360.0 / cycle_time;
        float x = x_rotation;
        float y = y_rotation;
        float z = z_rotation + newAngle;
        rotation newRotation = llEuler2Rot(<x, y, z> * DEG_TO_RAD);
        newRotation = newRotation * base_rot;
        llSetLinkPrimitiveParamsFast(LINK_THIS, [PRIM_ROTATION, newRotation]);
    }
}
mostly harmless.
User avatar
Kayaker Magic
Posts: 354
Joined: Sun Dec 01, 2013 8:40 am
Has thanked: 52 times
Been thanked: 393 times

Re: llSetLinkPrimitiveParamsFast is slower than expected

Post by Kayaker Magic »

Try using llSetKeyframedMotion to make your object rotate. You can call it once a second if you need to change the rotation often and let it run between timer events. This uses less server resources than calling llSetLinkPrimitiveParameters 32 times a second.

I use llSetKeyframedMotion for all my non-physical vehicles and critters. I do my own physics calculations once a second (or twice a second for a responsive vehicle like a windsurfer) and have llSetKeyframedMotion interpolate the position and rotation between calculations.
These users thanked the author Kayaker Magic for the post (total 2):
Saros EclipseIlan Tochner
User avatar
Handy Low
Posts: 231
Joined: Fri Nov 08, 2013 3:38 pm
Location: Yorkshire, England
Has thanked: 207 times
Been thanked: 140 times
Contact:

Re: llSetLinkPrimitiveParamsFast is slower than expected

Post by Handy Low »

And another solution is to use llTargetOmega, which has the advantage of deferring all the processing to the client.
These users thanked the author Handy Low for the post:
Ilan Tochner
Handy Low
User avatar
Saros Eclipse
Posts: 9
Joined: Tue Aug 09, 2016 11:46 pm
Location: Lynnwood, WA
Has thanked: 1 time
Been thanked: 4 times

Re: llSetLinkPrimitiveParamsFast is slower than expected

Post by Saros Eclipse »

Handy Low wrote:And another solution is to use llTargetOmega, which has the advantage of deferring all the processing to the client.
I use llTargetOmega for things that don't need to be synchronized. Unfortunately a few of the items need to stay in sync, and the scripts wouldn't sync up unless they were started at the same instant and never interrupted.
mostly harmless.
Post Reply