【发布时间】:2018-06-24 19:28:55
【问题描述】:
我的网络应用上有图表,每次收到新信息时我都需要更新图表。
现在我正在做模拟,所以我用大约 100000 个数据回测(在 json 中)(但如果浏览器和硬件可以处理它,可能是数百万个)。
因此,我需要尽可能优化我的代码。
我有这样的对象:
var trades = {"1515867288390":{price:"10", quantity:"500"},
"1515867289541":{price:"9", quantity:"400"},
"1515867295400":{price:"11", quantity:"750"},
"1515867296500":{price:"7", quantity:"1100"},
...}
每次我在交易中扫描一个对象时,我都想获得最后 X 秒的中间价格,所以我有一个 $.each(trades, getAverage...)
getAverage = function (trade_time) {
var total_quantity = 0;
var total_trade_value = 0;
var startfrom = trade_time - duration;
Object.keys(trades).forEach(function (time) {
if (time < startfrom)
delete trades[time];
});
$.each(trades, function (key, value) {
total_quantity += parseFloat(value.quantity);
total_trade_value += (value.price * value.quantity);
});
var average = (total_trade_value / total_quantity);
return average;
}
80000 笔交易的平均执行时间约为 7.5 秒。
我猜不错,但问题是我需要var startfrom = trade_time - duration 中的持续时间可以调整,这会导致问题,因为我的 getAverage 函数会根据 startfrom 删除所有元素,它本身取决于持续时间,所以如果在开始持续时间 = 10,然后持续时间更改为 20,无论如何获取平均值只能回顾最后 10 秒。
一种解决方案是复制数组以保留“完整”副本,但我的函数每次都会迭代所有元素,而且速度会慢很多。 我尝试过的第二个选项是不删除该项目并使用:
Object.keys(trades).filter(t => t>=startfrom).forEach(function (time) {
var value = trades[time];
total_quantity += parseFloat(value.quantity);
total_trade_value += (value.price * value.quantity);
});
它慢了大约 300 倍,真是糟糕的选择,我想知道你会怎么想?
谢谢。
PS:我正在考虑使用数组,因为我的键总是数字(时间戳),但是如果我使用数组,我最终会得到数百万个空索引,这不会再次降低性能吗?
【问题讨论】:
-
你为什么使用
$.each,这几乎肯定比使用等效的内置方法要慢?您已经完成了Object.keys(trades),因此请存储密钥并重新使用它们。delete trades[type]中的type来自哪里? -
由于对象没有排序,你不能在任何有意义的意义上“返回”,你必须将键放入一个数组并对其进行排序,这样你就可以在一个一定的时间范围。最好将您的数据放入
[{time:1515867288390, price:"10", quantity:"500"},...]之类的数组中。如果按顺序推送,它们已经很容易排序,以便在一个范围内的交易中前后移动。 -
在您当前的对象中,时间用于属性名称,因此具有相同时间值的第二次交易将覆盖第一次,即它不能有重复的时间值或两个相同的交易时间。最后一个获胜。
-
对您的逻辑没有帮助,但性能的一个好步骤是将其移动到 webWorker 中,该 webWorker 将直接连接到套接字。这样你甚至可以在不污染主线程和用户体验的情况下处理内存垃圾。
-
Websocket 是有状态的,是吗?因此,在每笔交易到达时对其进行转换并将其推送到数组中(如果交易可能无序到达,则将其拼接到数组中)。不择手段,确保数组按时间戳顺序保存。然后,当您的非套接字代码从套接字(如
trades)获取数据并计算出平均值时,您想要的数据将始终位于数组的一端。一旦达到不合格交易,计算就会停止(跳出循环)。
标签: javascript jquery performance ecmascript-6 javascript-objects