Ios Swift函数执行时间度量问题

Ios Swift函数执行时间度量问题,ios,arrays,swift,sorting,set,Ios,Arrays,Swift,Sorting,Set,我有两个功能,它们是: extension Array where Element: Hashable { func uniqueOrderly() -> [Element] { let startTime = CFAbsoluteTimeGetCurrent() var set = Set<Element>() var array = [Element]() for element in self {

我有两个功能,它们是:

extension Array where Element: Hashable {
    func uniqueOrderly() -> [Element] {
        let startTime = CFAbsoluteTimeGetCurrent()
        var set = Set<Element>()
        var array = [Element]()
        for element in self {
            if set.contains(element) {
                continue
            }
            set.insert(element)
            array.append(element)
        }
        let timeElapsed = CFAbsoluteTimeGetCurrent() - startTime
        print("Time for uniqueOrderly: \(timeElapsed)")
        return array
    }
}
我正在阵列上测量函数执行时间

即:

let arrayToFilter = [1,2,4,6,1,2,5,7,9,3,3,1,1,2,4,6,1,2,5,7,9,3,3,1,1,2,4,6,1,2,5,7,9,3,3,1,1,2,4,6,1,2,5,7,9,3,3,1,1,2,4,6,1,2,5,7,9,3,3,1,1,2,4,6,1,2,5,7,9,3,3,1,1,2,4,6,1,2,5,7,9,3,3,1,1,2,4,6,1,2,5,7,9,3,3,1,1,2,4,6,1,2,5,7,9,3,3,1,1,2,4,6,1,2,5,7,9,3,3,1,1,2,4,6,1,2,5,7,9,3,3,1,1,2,4,6,1,2,5,7,9,3,3,1,1,2,4,6,1,2,5,7,9,3,3,1,1,2,4,6,1,2,5,7,9,3,3,1,1,2,4,6,1,2,5,7,9,3,3,1,1,2,4,6,1,2,5,7,9,3,3,1,1,2,4,6,1,2,5,7,9,3,3,1,1,2,4,6,1,2,5,7,9,3,3,1,1,2,4,6,1,2,5,7,9,3,3,1,1,2,4,6,1,2,5,7,9,3,3,1,1,2,4,6,1,2,5,7,9,3,3,1,1,2,4,6,1,2,5,7,9,3,3,1,1,2,4,6,1,2,5,7,9,3,3,1,1,2,4,6,1,2,5,7,9,3,3,1]
实际函数调用和结果的顺序如下:

arrayToFilter.unique() //Time for unique: 0.00012195110321044922
arrayToFilter.uniqueOrderly() Time for uniqueOrderly: 0.02329099178314209
但是,当我更改函数调用的顺序时,我的
unique()
函数会显示可怕的时间度量

arrayToFilter.uniqueOrderly() //Time for uniqueOrderly: 0.0013059377670288086
arrayToFilter.unique() //Time for unique: 8.940696716308594e-06
那么我的问题是,为什么在不同的函数调用顺序下会出现这种情况?另外,当我在for循环中运行这些测试时,测量结果是完全不同的。(大约+-1秒)

所有的mesurants都是在操场和真实的iOS应用程序中完成的,带有发布构建设置(在模拟器上)

测试规格:

Xcode版本10.1

Swift 4.2

您的
unique()
实现在计算
unique
之前先计算经过的时间
unique
是一个计算的var,在访问时进行评估

对于像这样相当短的列表,您的
uniqueordery()
实现仍然比
unique()
慢,因为插入到集合中比几乎总是在前几个元素中命中的线性搜索要昂贵

至于排序问题,这几乎可以肯定是您如何测试它的一个产物。微观分析非常具有挑战性。我通过将它们放入自己的
.swift
文件并作为
swift-O
运行来测试它们。但是,如果我按照您的方式将它们放在同一个文件中,并修复
unique()
以实际计时其活动,那么当以
swift-O
运行时,时间是相当一致的:

经过更多的测试后,我怀疑这些差异部分是内存分配(内存以块的形式从操作系统中获取,因此第一个分配器比第二个分配器付出更高的代价)和L1缓存。如果对两个不同的数组(指向内存缓存)进行排序,几乎所有差异都会消失。但是这个算法对数组的组成也非常敏感,因为它有很多重复项

无论如何,这种微观优化是没有意义的。你要整天追鬼。很难在微小的数据块上测试微小的代码片段,并以适用于实际使用的方式对其进行优化。至少,您需要非常大的阵列,并在许多不同类型的发行版上进行测试(大量的重复版本而很少)。您必须在操场外进行测试,并且必须使用优化器。

您的
unique()
实现在计算
unique
之前计算经过的时间
unique
是一个计算的var,在访问时进行评估

对于像这样相当短的列表,您的
uniqueordery()
实现仍然比
unique()
慢,因为插入到集合中比几乎总是在前几个元素中命中的线性搜索要昂贵

至于排序问题,这几乎可以肯定是您如何测试它的一个产物。微观分析非常具有挑战性。我通过将它们放入自己的
.swift
文件并作为
swift-O
运行来测试它们。但是,如果我按照您的方式将它们放在同一个文件中,并修复
unique()
以实际计时其活动,那么当以
swift-O
运行时,时间是相当一致的:

经过更多的测试后,我怀疑这些差异部分是内存分配(内存以块的形式从操作系统中获取,因此第一个分配器比第二个分配器付出更高的代价)和L1缓存。如果对两个不同的数组(指向内存缓存)进行排序,几乎所有差异都会消失。但是这个算法对数组的组成也非常敏感,因为它有很多重复项


无论如何,这种微观优化是没有意义的。你要整天追鬼。很难在微小的数据块上测试微小的代码片段,并以适用于实际使用的方式对其进行优化。至少,您需要非常大的阵列,并在许多不同类型的发行版上进行测试(大量的重复版本而很少)。您必须在操场外进行测试,并且必须使用优化器。

首先,您在哪里进行测试?确保您正在真实设备上的优化构建中进行测试。永远不要在操场上测试性能。@rmaddy我用你们要求的信息更新我的问题。@rmaddy若你们需要,我可以添加带有时间执行下降的日志。首先,你们在哪里测试这个?确保您正在真实设备上的优化构建中进行测试。永远不要在操场上测试性能。@rmaddy我用你们要求的信息更新我的问题。@rmaddy若你们需要,我可以添加带有时间执行下降的日志。
arrayToFilter.uniqueOrderly() //Time for uniqueOrderly: 0.0013059377670288086
arrayToFilter.unique() //Time for unique: 8.940696716308594e-06
Time for uniqueOrderly: 1.800060272216797e-05
[1, 2, 4, 6, 5, 7, 9, 3]
Time for unique: 2.0265579223632812e-06
[1, 2, 4, 6, 5, 7, 9, 3]

Time for unique: 2.002716064453125e-05
[1, 2, 4, 6, 5, 7, 9, 3]
Time for uniqueOrderly: 2.9802322387695312e-06
[1, 2, 4, 6, 5, 7, 9, 3]