【发布时间】:2016-04-17 12:55:17
【问题描述】:
在尝试学习 Swift 2.2 时,我在尝试分配许多小对象(基本上是 262144 个元素的 BST)时面临严重的性能下降。我当前的基准测试是我几年前编写的一个旧片段的 Java 1.8.0_74 编译,在我的 2012 Retina Macbook Pro 上,它在 59 秒(59036178 微秒)内执行。我可以通过 Instruments 观察到的问题是,每次迭代我都会得到几十个 swift_retain_ 和 swift_release。不知道如何避免它们:
import Foundation
import Darwin;
import Foundation
public class BinarySearchTree<T : Comparable> {
private var _value : T?;
private var _leftTree : BinarySearchTree<T>?;
private var _rightTree : BinarySearchTree<T>?;
public init(value : T) {
_value = value;
}
var value : T? {
get {
return self._value;
}
set {
self._value = newValue;
}
}
var leftTree : BinarySearchTree<T>? {
get {
return self._leftTree;
}
set {
self._leftTree = newValue;
}
}
var rightTree : BinarySearchTree<T>? {
get {
return self._rightTree;
}
set {
self._rightTree = newValue;
}
}
public func add(newValue : T) -> BinarySearchTree<T> {
var navigator : BinarySearchTree<T>?;
var subtree : BinarySearchTree<T>?;
var done : Bool?;
done = false;
navigator = self;
while (!done!) {
if (newValue < navigator?.value) {
subtree = navigator?.leftTree;
if (subtree != nil) {
navigator = subtree;
} else {
let newNode = BinarySearchTree<T>(value: newValue);
navigator!.leftTree = newNode;
done = true;
}
} else if (newValue > navigator?.value) {
subtree = navigator?.rightTree;
if (subtree != nil) {
navigator = subtree;
} else {
let newNode = BinarySearchTree<T>(value: newValue);
navigator?.rightTree = newNode;
done = true;
}
} else {
done = true;
}
}
return self;
}
} /* cut remove/search methods */
这是我为测试运行编写的测试代码
let count : Int32 = 262144;
let base : Int32 = 65536;
let target : Int32 = count + 1;
var info = mach_timebase_info(numer:0, denom:0);
var timebase = mach_timebase_info(&info);
let numer = UInt64(info.numer);
let denom = UInt64(info.denom);
let norm = UInt64(numer/denom);
let check1 = (mach_absolute_time() * norm);
var root = BinarySearchTree<Int32>(value:base);
for var loop in 0 ... count-1 {
if (loop % 1000 == 0) {
print(loop);
}
root = root.add(loop);
}
let check2 = (mach_absolute_time() * norm);
print("Creation phase microseconds: [" + String((check2 - check1) / 1000) + "]");
我尝试搜索特定的快速释放/保留问题,但没有成功,我不知道如何继续。谢谢大家
【问题讨论】:
-
你确定分配是真正的问题吗?您按递增顺序插入数字,这会使 BST 退化为链表并导致查找速度变慢。 – 如果你插入随机数会发生什么?
-
嗨马丁,我知道退化很快,但这只是一个检查内存分配的测试循环。最坏的情况是,262k 元素的列表多年来仍然无法匹配任何 Mac。我使用类而不是结构(不好,我知道)以避免不必要的内存复制。不用说,-Ofast 和 Release 构建。
-
我改为使用
root = root.add(Int32(arc4random_uniform(UInt32(count))))运行您的代码,它在大约 0.5 秒内完成(发布配置)。分配的数量大致相同! – 这就是为什么我认为线性查找是问题,而不是分配。 -
这确实很有趣。即使考虑到在 add 方法中会跳过重复值,它确实将问题移向了不同的方向,但是对于这么小的数据集,指针/引用导航真的会成为问题吗?对于Java版本肯定不行
-
您是否在 Java 中尝试过相同的操作,即将 262144 递增的数字插入到具有相同算法的 BST 中?花了多长时间(与 262144 个随机数相比)?