1

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

String我的问题是,当您拥有 a并且您想高速获取它的字符时,哪个性能更快,myString.charAt(i)或者拥有var a:Array = myString.split('');然后像这样获取它们a[i];

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

4

3 回答 3

4

您始终可以通过在代码执行之前和之后使用 getTimer 来测试自己,看看在您的情况下什么更有效,以及它是否重要:

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

//You code here

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

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

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

于 2012-11-19T17:31:31.857 回答
2

benbjo 的建议是中肯的。如果性能确实是一个问题,那么最好的测试用例是您实际使用代码的情况,尤其是因为垃圾收集和 JIT'er 使得事情在实际性能方面变得不可预测。

也就是说,该charAt方法通常会比split(). 在内存方面应该没有太大区别——两种方法都是为每个字符创建一个新字符串。除此之外,split()显然还创建了一个额外的数组。

这两种方法的比较:

字符:

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

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

Min = 单次运行的最短时间

Max = 单次运行的最长时间

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

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

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

于 2012-11-19T21:35:22.707 回答
1

好的,这对于评论来说太多了。

首先,很难说出你想要做什么以及为什么需要比较这些东西,但正如我已经说过的那样。如果您正在研究序列化 - 学习使用内置序列化。当有人重新发明轮子时,我已经看到这种情况发生了很多次,并且在所有可能的方面都比内置的轮子差了几个数量级。这样做的唯一借口是,如果你正在学习事情是如何运作的。

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

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

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

第三快的可能是ByteArrayBitmapData

但是,如果您在序列化中做了一些愚蠢的事情,这一切都绝对不重要。为了正确地做到这一点,你真的需要一个好的策略,你需要很好地理解信息论,以预测这种或其他压缩数据的方式将如何减小大小,或者更容易或更快地实现等等在。在这个领域有很多糟糕的决定变得流行的好例子。Base64 编码、XML 和 JSON 格式是卡住的粗心设计的例子。

谈到 Flash,选择是绝对显而易见的,在各个方面,AMF 都比您可能拥有的任何选项都要好。您需要对自己正在做的事情有一个非常深入的了解,自己动手并做得更好。

PS. One more note: if you don't want to make additional allocations with charAt - you can use substr or substring, because these don't cause reallocations, but will prevent the source string from being deallocated until the subtracted string lives.

于 2012-11-19T22:27:50.303 回答