通用序列和生成器的极端性能问题

时间:2014-08-05 05:00:36

标签: performance generics swift

我正在尝试创建自己的Generic序列类型。我可以创建的最简单的示例显示性能问题:

// Warning, this code will cause Xcode to hang if you run this in a playground
// Instead I recommend running it in the REPL  or running it with the command
// line tool

struct TakeGenerator<T: GeneratorType>: GeneratorType {
    typealias Element = T.Element

    var generator: T

    mutating func next() -> Element? {
        return self.generator.next()
    }
}

struct Take<T: SequenceType>: SequenceType {
    typealias Generator = TakeGenerator<T.Generator>

    let seq: T
    let test: ((element: T.Generator.Element) -> Bool)?

    func generate() -> Generator {
        return Generator(generator: seq.generate())
    }
}

// NOTE: The times below reflect how long it takes to run this code from 
// the command line with only that line uncommented (other than the type
// declarations)
//
// The command I use is: `time xcrun swift <filename>`

var array = [1,2,3,4]
Take(seq: array, test: {$0 < 3}) // 0.104 seconds to execute
Take(seq: [1,2,3,4], test: nil) // 0.100 seconds to execute
Take(seq: ([1,2,3,4] as [Int]), test: {$0 < 3}) // 0.140 seconds to execute
Take(seq: [1,2,3,4], test: {$0 < 3}) // 17.939 seconds to execute

注意:显然这是一种无用的类型,因为它只生成与生成的类型相同的东西,但我的实际类型稍微复杂一些。

正如您在我的代码注释中所看到的,构造函数的最后一个版本存在极端的性能问题。它不需要花费十分之一秒,而是花费将近18秒。

我甚至没有做任何实际的一代。我想它与确定类型有关,因为如果数组都是文字并且提供了测试方法,那只是一个问题。如果我将测试属性声明更改为硬编码为Int:

,也没有性能问题
let test: ((element: Int) -> Bool)?

任何人都可以了解可能导致此性能问题的原因以及我如何解决这个问题?

1 个答案:

答案 0 :(得分:2)

这绝对是一个类型推断问题。使用swiftc test.swift进行编译会占用大部分时间;正在运行./test。此外,sample显示大部分时间花在

Call graph:
    2677 Thread_113719   DispatchQueue_1: com.apple.main-thread  (serial)
      2677 start  (in libdyld.dylib) + 1  [0x7fff946715c9]
        2677 main  (in swift) + 1725  [0x105919a2d]
          2677 frontend_main(llvm::ArrayRef<char const*>, char const*, void*)  (in swift) + 1960  [0x10591b908]
            2677 swift::CompilerInstance::performSema()  (in swift) + 2064  [0x105b7de80]
              2677 swift::performTypeChecking(swift::SourceFile&, swift::TopLevelContext&, unsigned int)  (in swift) + 1464  [0x106830d08]
                2677 swift::TypeChecker::typeCheckTopLevelCodeDecl(swift::TopLevelCodeDecl*)  (in swift) + 136  [0x10687d518]
                  2677 swift::ASTVisitor<(anonymous namespace)::StmtChecker, void, swift::Stmt*, void, void, void, void>::visit(swift::Stmt*)  (in swift) + 291  [0x10687d683]
                    2677 swift::TypeChecker::typeCheckExpression(swift::Expr*&, swift::DeclContext*, swift::Type, swift::Type, bool, swift::FreeTypeVariableBinding, swift::ExprTypeCheckListener*)  (in swift) + 971  [0x10683a2ab]
                      2677 swift::constraints::ConstraintSystem::solve(llvm::SmallVectorImpl<swift::constraints::Solution>&, swift::FreeTypeVariableBinding)  (in swift) + 363  [0x10681e8fb]
                        2677 swift::constraints::ConstraintSystem::solve(llvm::SmallVectorImpl<swift::constraints::Solution>&, swift::FreeTypeVariableBinding)  (in swift) + 945  [0x10681eb41]
                          ...

File a bug!