【发布时间】:2016-12-27 10:34:46
【问题描述】:
我在 JavaScript 中实现了以下链表数据结构:
class Node {
constructor(data, list) {
this.data = data;
this.list = list;
this.prev = null;
this.next = null;
}
remove() {
if (this.prev) {
this.prev.next = this.next;
} else {
this.list.start = this.next;
}
if (this.next) {
this.next.prev = this.prev;
} else {
this.list.end = this.prev;
}
this.next = null;
this.prev = null;
this.list.length -= 1;
}
}
class LinkedList {
constructor() {
this.end = null;
this.start = null;
this.length = 0;
}
append(data) {
const node = new Node(data, this);
if (!this.start) {
this.start = node;
}
if (this.end) {
node.prev = this.end;
this.end.next = node;
}
this.end = node;
this.length += 1;
return data;
}
remove() {
if (this.end) {
return this.end.remove();
}
}
*[Symbol.iterator]() {
let current = this.start;
while (current) {
yield current;
current = current.next;
}
}
}
module.exports = LinkedList;
我用它来更新动画列表:
static update(timeDelta) {
for (let node of this.animations) {
const animation = node.data;
if (animation.animating) {
animation.update(timeDelta);
} else {
node.remove();
}
}
}
node.remove() 行在我的游戏中造成了非常明显的延迟。我怀疑它正在触发垃圾收集。反常的,如果我注释掉node.remove()这一行,让链表永远增长,游戏就会顺利运行。
动画不断被添加和删除。我在动画update函数中添加了一些日志记录:
start iterating linked list
removing
ms elapsed: 0.45499999999992724
end iterating
start iterating linked list
removing
ms elapsed: 0.455000000000382
end iterating
start iterating linked list
removing
ms elapsed: 0.13000000000010914
end iterating
start iterating linked list
(13) updating
ms elapsed: 2.200000000000273
end iterating
您可以看到链表每秒迭代多次,偶尔会删除一个节点。
我怎样才能从我的列表中实现 O(1) 删除而不实际导致性能下降?
【问题讨论】:
-
使用链表的目的是什么?不能只使用数组或对象吗?
-
我可以使用数组,但我试图避免使用
splice,这将不得不将所有元素转移过来。我想要恒定时间删除元素。 -
然后就可以使用对象了。
-
而不是取消引用数据从而导致 GC 命中。将对象放在另一个数组中,并将其用于您创建的下一个对象,假设它们具有相同的数据模式和大小。如果没有,那么您只需要保留数据,直到 GC 命中不会影响应用程序。
-
@Gothdo 你的意思是我应该将这些动画作为键值对存储在一个对象中,然后在它们上使用
delete关键字吗? @Blindman67 这是个好主意。所以这个链表抽象因为 GC 就没有意义了?
标签: javascript data-structures linked-list garbage-collection ecmascript-6