我正在写一个赌场游戏,我需要加密我通过套接字传递的所有数据,所以我想要尽可能多的性能,因为加密和解密可能会发生很多,我不希望它迟钝。
String
我的问题是,当您拥有 a并且您想高速获取它的字符时,哪个性能更快,myString.charAt(i)
或者拥有var a:Array = myString.split('');
然后像这样获取它们a[i];
我的for
周期可能会运行 60-100 次或更多。提前致谢
我正在写一个赌场游戏,我需要加密我通过套接字传递的所有数据,所以我想要尽可能多的性能,因为加密和解密可能会发生很多,我不希望它迟钝。
String
我的问题是,当您拥有 a并且您想高速获取它的字符时,哪个性能更快,myString.charAt(i)
或者拥有var a:Array = myString.split('');
然后像这样获取它们a[i];
我的for
周期可能会运行 60-100 次或更多。提前致谢
您始终可以通过在代码执行之前和之后使用 getTimer 来测试自己,看看在您的情况下什么更有效,以及它是否重要:
var testTime:int;
var before:int = getTimer();
//You code here
testTime = getTimer() - before;
trace(testTime);
所以基本上,你输入你的两个算法并检查执行需要多少时间。
编辑:Apocalyptic0n3 自然是正确的。最好使用 new Date.time() 而不是 getTimer() 因为它在冻结的情况下更准确。
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 团队花了很多时间优化字符串操作、连接等。
好的,这对于评论来说太多了。
首先,很难说出你想要做什么以及为什么需要比较这些东西,但正如我已经说过的那样。如果您正在研究序列化 - 学习使用内置序列化。当有人重新发明轮子时,我已经看到这种情况发生了很多次,并且在所有可能的方面都比内置的轮子差了几个数量级。这样做的唯一借口是,如果你正在学习事情是如何运作的。
当然,如果您计划处理数十万个文件 - 您可以用 C 编写并在 AIR 或类似的语言中使用本机扩展,这肯定会赢。
现在,如果您想知道处理字符串数据的最快方法,那不是我们的选择。最快的方法是将其加载到域的内存中并使用所谓的“炼金术操作码”来访问数据字节。如果字符串使用 8 位编码,这将非常快,如果使用 Unicode,则不会那么快。显然,如果您要测试之前建议的内容,这也会影响您的测试。
第二个最佳选择:由整数组成的向量,它们是字符代码。这些更好地优化并使用不同的内存分配模型。
第三快的可能是ByteArray
或BitmapData
。
但是,如果您在序列化中做了一些愚蠢的事情,这一切都绝对不重要。为了正确地做到这一点,你真的需要一个好的策略,你需要很好地理解信息论,以预测这种或其他压缩数据的方式将如何减小大小,或者更容易或更快地实现等等在。在这个领域有很多糟糕的决定变得流行的好例子。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.