String的分裂或charAt

时间:2012-11-19 17:10:43

标签: string actionscript-3 flash

我正在写一个赌场游戏,我需要加密我通过套接字传递的所有数据,所以我想要尽可能多的性能,因为加密和解密可能会发生很多,而且我不会希望它有点滞后。

我的问题是,如果你有一个String并希望高速获取它的角色myString.charAt(i)或拥有var a:Array = myString.split('');然后让它们像这样,那么性能会更快a[i];

我的for周期可能会达到60-100次或更多次。提前致谢

3 个答案:

答案 0 :(得分:4)

您可以随时测试自己,看看在您的情况下哪些更有效,以及在执行代码之前和之后使用getTimer是否重要:

var testTime:int;
var before:int = getTimer();

//You code here

testTime = getTimer() - before;
trace(testTime);

所以基本上,你输入两个算法并检查执行的时间。

编辑:Apocalyptic0n3自然是正确的。最好使用新的Date.time()而不是getTimer(),因为它在冻结时更准确。

答案 1 :(得分:1)

benbjo的建议是坚实的。如果性能真的是一个问题,那么最好的测试用例就是你实际上要使用你的代码的情况,尤其是因为垃圾收集和JIT'er使得事情无法预测实际表现。

尽管如此,charAt方法一般比split()快20-50%。记忆方面应该没有太大的区别 - 两种方法都是为每个角色创建一个新的字符串。除此之外,split()显然还会创建一个额外的数组。

这两种方法的比较:

的charAt:

var s:String = "";
for (var j:int = 0; j < len; j++)
{
    // The string concat seems to be enough to confuse the JIT compiler.
    s += v.charAt(j);
}

分裂:

var s:String = "";
var arr:Array = v.split("");
for (var j:int = 0; j < len; j++)
{
    // The string concat seems to be enough to confuse the JIT compiler.
    // Using just arr[j] seems to be unfairly optimized.
    s += arr[j];
}

相关的已编译ABC字节代码在两者之间是可预测的相同,除了调用split,以及数组访问与调用charAt()之外。换句话说,ASC编译器没有疯狂的优化特技(无论如何都是罕见的)。

10次运行,每次上述代码1000次迭代,在发布播放器上发布版本:

FP WIN 11,5,502,110           :  #Runs  #Iter           Avg           Min           Max          Iter
charAt :: string length: 50   :     10   1000        9.0 ms          6 ms         10 ms     0.0090 ms
split  :: string length: 50   :     10   1000       13.0 ms          8 ms         19 ms     0.0130 ms
charAt :: string length: 500  :     10   1000       68.5 ms         58 ms         97 ms     0.0685 ms
split  :: string length: 500  :     10   1000      100.5 ms         86 ms        136 ms     0.1005 ms
charAt :: string length: 1000 :     10   1000      149.3 ms        119 ms        202 ms     0.1493 ms
split  :: string length: 1000 :     10   1000      201.2 ms        162 ms        261 ms     0.2012 ms
charAt :: string length: 2000 :     10   1000      283.8 ms        230 ms        378 ms     0.2838 ms
split  :: string length: 2000 :     10   1000      326.9 ms        307 ms        423 ms     0.3269 ms
charAt :: string length: 4000 :     10   1000      575.8 ms        475 ms        752 ms     0.5758 ms
split  :: string length: 4000 :     10   1000      665.0 ms        609 ms        888 ms     0.6650 ms
charAt :: string length: 5000 :     10   1000      650.9 ms        581 ms        915 ms     0.6509 ms
split  :: string length: 5000 :     10   1000      863.4 ms        769 ms       1219 ms     0.8634 ms
charAt :: string length: 10000:     10   1000     1300.5 ms       1155 ms       1707 ms     1.3005 ms
split  :: string length: 10000:     10   1000     1797.3 ms       1534 ms       2461 ms     1.7973 ms

平均值=每次运行的平均时间(1000次迭代)

最小=单次运行的最短时间

最大=单次运行的最长时间

Iter =单次迭代的平均时间。

运行之间的差异相当大,可能是由于在某些运行期间发生了垃圾收集。但结果始终有利于charAt()。在每次运行之前进行一次split()调用而不是在每次运行中重做它并没有太大的区别。换句话说,性能的差异确实在于访问数组比调用charAt()慢。然而,这不是巨大的差异,例如,您可以使用indexOf而不是正则表达式来搜索字符串。

一般来说,虽然它不是一个严格的规则,但对于像字符串操作这样的简单任务最明显的方法可能会更快。 FlashPlayer团队花了很多时间来优化字符串操作,连接等。

答案 2 :(得分:1)

好的,这对评论来说太过分了。

首先,很难说你想要做什么,为什么你需要比较这些东西,但正如我已经说过的那样。如果您正在研究序列化 - 学习使用内置序列化。我已经看到它发生了很多次,当有人重新发明轮子时,数量级各种可能的方面,然后是内置的。真正做到这一点的唯一理由是,如果你正在学习如何运作。

当然,如果您计划处理数十万个文件 - 您可以使用C语言编写并在AIR中使用原生扩展或其他类似文件,这肯定会赢。

现在,如果您想知道处理字符串数据的最快方法,那么这不是我们的选择。最快的方法是将其加载到域的内存中,并使用所谓的“Alchemy操作码”来访问数据字节。如果字符串使用8位编码,这将非常快,如果它们使用Unicode,则速度不会太快。显然,如果您要测试之前建议的内容,这也会影响您的测试。

第二个最佳选项:由整数组成的向量,它是char代码。这些更好地优化并使用不同的内存分配模型。

第三快的可能是ByteArrayBitmapData

如果你在序列化中做一些愚蠢的事情,那么这一切都绝对不重要。为了做到这一点,你真的需要一个好的策略,你需要在良好的层面上理解信息理论,以预测压缩数据的方式或其他方式是否会减小规模,或者更容易或更快地实施等等。在这个领域中有许多不好的决定很好的例子变得流行。 Base64编码,XML和JSON格式是坚持不懈的设计的例子。

说到Flash,选择是绝对明显的,在各方面AMF都比你在桌面上的任何选项更好。你需要对你正在做的事情有一个非常深入的了解,自己动手并使其变得更好。

PS。还有一点需要注意:如果您不想使用charAt进行其他分配 - 您可以使用substrsubstring,因为这些不会导致重新分配,但会阻止源字符串从被解除分配到减去的字符串存在。