Difference between revisions of "LSL Script Efficiency/zh-Hans"

From Second Life Wiki
Jump to navigation Jump to search
Line 6: Line 6:
<div style="padding: 0.5em;">
<div style="padding: 0.5em;">


效率是指一段特定的脚本要实现某个目标需要占用资源的多少。它一般是指脚本执行的速度,但不限于此
效率是指一段特定的脚本要实现某个目标需要占用资源的多少。它一般是指脚本执行的速度,但不限于此。
 
以下是几点需要注意的事项,大体上按重要性排序:
以下是几点需要注意的事项,大体上按重要性排序:


Line 29: Line 27:


一个对象中的每个无用脚本都耗费每帧0.001到0.003的脚本时间,所以脚本越少越好。
一个对象中的每个无用脚本都耗费每帧0.001到0.003的脚本时间,所以脚本越少越好。
* 如果你需要使用一组“按钮”,不要在每个prim中加入脚本,而是在主脚本中用
[[llDetectedLinkNumber]]来侦测到底是哪个按钮被触发了。 
* 如果你需要改变子prims的color、alpha或texture,不要在每个prim中加入脚本,而是使用
[[llSetLinkAlpha]],[[llSetLinkColor]],[[llSetLinkTexture]],或[[llSetLinkPrimitiveParams]]
* '''永远不要'''在每个prim(特别是对于包含在较大的linkset中的)中加入脚本来监听0号频道(或任何


其它的频道)。对于效率而言这也许是最糟糕的事情,不幸的是这是经常发生的。
* 如果你需要使用一组“按钮”,不要在每个prim中加入脚本,而是在主脚本中用[[llDetectedLinkNumber]]来侦测到底是哪个按钮被触发了。 
* 如果你需要改变子prims的color、alpha或texture,不要在每个prim中加入脚本,而是使用[[llSetLinkAlpha]],[[llSetLinkColor]],[[llSetLinkTexture]],或[[llSetLinkPrimitiveParams]]。
* '''永远不要'''在每个prim(特别是对于包含在较大的linkset中的)中加入脚本来监听0号频道(或任何其它的频道)。对于效率而言这也许是最糟糕的事情,不幸的是这是经常发生的。
* 应考虑[[XyzzyText]]来代替[[XyText]]。
* 应考虑[[XyzzyText]]来代替[[XyText]]。


最起码的,如果你发现有必要在每个prim中加入脚本,也要停下来想想是否有其它的方法用更少的脚本完
最起码的,如果你发现有必要在每个prim中加入脚本,也要停下来想想是否有其它的方法用更少的脚本完成它。总会有变通的方法,这种变通在你的程序中是否可行完全取决于你。
 
成它。总会有变通的方法,这种变通在你的程序中是否可行完全取决于你。


</div></div>
</div></div>
Line 57: Line 46:
<div style="padding: 0.5em;">
<div style="padding: 0.5em;">


下面的代码会取得调用每个函数的时间
下面的代码会取得调用每个函数的时间,请到[[Talk:LSL_Script_Efficiency|discussion]]提出修改意见。由于任何微小的改动都会影响测量的精准,请不要在经过讨论之前修改这里的代码。请确保这些代码与它的注释都与[[Efficiency Tester]]页面保持一致。


请到[[Talk:LSL_Script_Efficiency|discussion]]提出修改意见。由于任何微小的改动都会影响测量的
感谢{{User|Xaviar Czervik}}提供原始代码,感谢{{User|Strife Onizuka}}调整了这些代码使它更加准确,也要感谢列在本文history中的所有贡献者。
 
精准,请不要在经过讨论之前修改这里的代码。请确保这些代码与它的注释都与[[Efficiency Tester]]
 
页面保持一致。
 
感谢{{User|Xaviar Czervik}}提供原始代码,感谢{{User|Strife Onizuka}}调整了这些代码使它更加准
 
确,也要感谢列在本文history中的所有贡献者。


<pre>
<pre>
Line 119: Line 100:
<div style="padding: 0.5em;">
<div style="padding: 0.5em;">


下面的数据是使用上面的代码在一个刚部署的(所以不是私有的)sim上取得的, 这个代码单独运行在一个
下面的数据是使用上面的代码在一个刚部署的(所以不是私有的)sim上取得的, 这个代码单独运行在一个HUD附件上。测试进行了20次并取了平均值。
 
HUD附件上。测试进行了20次并取了平均值。
   ++a:    0.173780 ms    std. dev.:  0.003393 ms
   ++a:    0.173780 ms    std. dev.:  0.003393 ms
   a += 1:  0.181720 ms    std. dev.:  0.013267 ms
   a += 1:  0.181720 ms    std. dev.:  0.013267 ms
Line 128: Line 107:
因此a++的执行时间比++a长40%(粗略估计)。
因此a++的执行时间比++a长40%(粗略估计)。


下面的数据同样是正确的,只是它没有用上面的函数,它用的是一个由{{User|Xaviar Czervik}}稍作优
下面的数据同样是正确的,只是它没有用上面的函数,它用的是一个由{{User|Xaviar Czervik}}稍作优化的版本。可能的话请大家用上面的函数重复测试。
 
化的版本。可能的话请大家用上面的函数重复测试。
   ++a:    0.364700 millis
   ++a:    0.364700 millis
   a += 1:  0.346900 millis
   a += 1:  0.346900 millis
Line 159: Line 136:
文本长度 ([[llSay]]() 全部使用1号频道):
文本长度 ([[llSay]]() 全部使用1号频道):
<pre>
<pre>
   1 Character:    1.242300 millis
   1 字节:    1.242300 millis
   10 Characters:  1.309700 millis
   10 字节:  1.309700 millis
   100 Characters: 1.965600 millis
   100 字节: 1.965600 millis
</pre>
</pre>

Revision as of 01:07, 22 December 2007

LSL脚本的执行效率

效率是指一段特定的脚本要实现某个目标需要占用资源的多少。它一般是指脚本执行的速度,但不限于此。 以下是几点需要注意的事项,大体上按重要性排序:

  • 为实现某种效果而使用大量的脚本。详见“设计高效率的脚本”
  • llSleep - 当脚本休眠时,这个函数每帧大概要多消耗0.2到0.3毫秒,使用timers会更好。
  • 频繁使用timers(<5秒)
  • Listen - 特别是对0号频道的监听。
  • 频繁地改变纹理(别人不得不下载它们)
  • 不恰当地用server/physical rotations代替omega
  • 非必要的事件处理函数(touch, collision, ...)
  • 大量的email或IM
  • 低效的脚本(如linear search)
  • 使用较大的循环(轮询法)

设计高效率的脚本

一个对象中的每个无用脚本都耗费每帧0.001到0.003的脚本时间,所以脚本越少越好。

  • 如果你需要使用一组“按钮”,不要在每个prim中加入脚本,而是在主脚本中用llDetectedLinkNumber来侦测到底是哪个按钮被触发了。
  • 如果你需要改变子prims的color、alpha或texture,不要在每个prim中加入脚本,而是使用llSetLinkAlphallSetLinkColorllSetLinkTexture,或llSetLinkPrimitiveParams
  • 永远不要在每个prim(特别是对于包含在较大的linkset中的)中加入脚本来监听0号频道(或任何其它的频道)。对于效率而言这也许是最糟糕的事情,不幸的是这是经常发生的。
  • 应考虑XyzzyText来代替XyText

最起码的,如果你发现有必要在每个prim中加入脚本,也要停下来想想是否有其它的方法用更少的脚本完成它。总会有变通的方法,这种变通在你的程序中是否可行完全取决于你。

微机-优化

有众多方法可以让脚本的执行速度更快,比如用++a代替a++,然而,这种优化在将来未必仍然有用。


代码到底运行得有多快

下面的代码会取得调用每个函数的时间,请到discussion提出修改意见。由于任何微小的改动都会影响测量的精准,请不要在经过讨论之前修改这里的代码。请确保这些代码与它的注释都与Efficiency Tester页面保持一致。

感谢Xaviar Czervik提供原始代码,感谢Strife Onizuka调整了这些代码使它更加准确,也要感谢列在本文history中的所有贡献者。

//IMPORTANT: Only perform tests in an empty region.
// To reduce contamination and be sure to wearing no attachments.
// Preferably do tests in a private sim with one on it.
// Don't move while performing the test.
// There is a margin of error so run the tests multiple times to determine it.

integer time() { // count milliseconds since the day began
    string stamp = llGetTimestamp(); // "YYYY-MM-DDThh:mm:ss.ff..fZ"
    return (integer) llGetSubString(stamp, 11, 12) * 3600000 + // hh
           (integer) llGetSubString(stamp, 14, 15) * 60000 +  // mm
           llRound((float)llGetSubString(stamp, 17, -2) * 1000000.0)/1000; // ss.ff..f
}

default {
  state_entry() {
    llOwnerSay((string) llGetFreeMemory());

    //test variables
    float counter;

    //framework variables
    float i = 0;
    float j = 0;
    float max = 10000; // 2ms of work takes 20 seconds to repeat 10,000 times, plus overhead

    float t0 = time();
    do {

      //test
      counter += 1;
      
    }while (++i < max);
    float t1 = time();
    do ; while (++j < max);
    float t2 = time();//remove the time required by the framework
    float elapsed = ((t1 - t0) - (t2 - t1))/max;
    llOwnerSay("The function in the loop took a total of " + (string)elapsed + " 

milliseconds.");
  }
}

效率

下面的数据是使用上面的代码在一个刚部署的(所以不是私有的)sim上取得的, 这个代码单独运行在一个HUD附件上。测试进行了20次并取了平均值。

  ++a:     0.173780 ms    std. dev.:  0.003393 ms
  a += 1:  0.181720 ms    std. dev.:  0.013267 ms
  a++:     0.243500 ms    std. dev.:  0.013816 ms

因此a++的执行时间比++a长40%(粗略估计)。

下面的数据同样是正确的,只是它没有用上面的函数,它用的是一个由Xaviar Czervik稍作优化的版本。可能的话请大家用上面的函数重复测试。

  ++a:     0.364700 millis
  a += 1:  0.346900 millis
  a++:     0.413700 millis

这是用相同的函数在for循环中所做的测试:

  ++a:     0.358370 millis
  a += 1:  0.351200 millis
  a++:     0.424600 millis

llOwnerSay v. llSay v. llShout v. llWhisper (监听0号频道):

  llOwnerSay(): 4.359000 millis
  llWhisper():  5.201000 millis
  llSay():      5.226000 millis
  llShout():   14.877000 millis

不同频道 (全部使用llSay()):

  -100000000: 1.226400 millis
  -100000:    1.254300 millis
  -100:       1.296100 millis
  -1:         1.292400 millis
  0:          5.226000 millis
  1:          1.242300 millis
  100:        1.249100 millis
  100000:     1.219700 millis
  100000000:  1.228700 millis

文本长度 (llSay() 全部使用1号频道):

   1 字节:    1.242300 millis
   10 字节:  1.309700 millis
   100 字节: 1.965600 millis