Swift WHOLE_MODULE_OPTIMIZATION可以缩短编译时间,但会导致lldb / Xcode崩溃

时间:2015-08-06 23:57:53

标签: ios xcode swift crash lldb

TL; DR

之前

SWIFT_WHOLE_MODULE_OPTIMIZATION = NO

  • 调试编译需要10-15分钟
  • 发布编译需要25分钟以上
  • po在LLDB中运作良好

之后

SWIFT_WHOLE_MODULE_OPTIMIZATION = YES

  • 调试编译需要1-2分钟
  • 发布编译大约需要8分钟
  • po 始终导致Xcode崩溃

知道为什么基于此信息的可怕编译时间,和/或为什么Xcode可能会崩溃?

DEETS

我正在开发一个大型的100%Swift项目(Objective-C中有第三方库,但我们所有的代码都是Swift)。我们编译时间非常糟糕,编译调试配置通常需要大约10-15分钟,编译发布配置需要30分钟以上。

由于可怕的编译时间,这个项目很难处理。我一直在寻找改进方法,特别是通过构建设置,几个月没有运气。我忽略的一件事是SWIFT_WHOLE_MODULE_OPTIMIZATION,特别是因为提及它会声称它会增加项目的编译时间。

所以前几天我们启用了SWIFT_WHOLE_MODULE_OPTIMIZATION并且看到我们的编译时间提高了10倍。

问题是,现在每当我们调试项目并尝试使用po myObject在lldb中打印对象时,Xcode会立即崩溃。以下是崩溃日志中的一些信息:

  

处理:Xcode [5860]
  路径:/Applications/Xcode.app/Contents/MacOS/Xcode
  标识符:com.apple.dt.Xcode
  版本:6.4(7720)
  构建信息:IDEFrameworks-7720000000000000~8
  App商品ID:497799835
  App外部ID:812725084
  代码类型:X86-64(原生)
  父进程:??? [1]
  负责人:Xcode [5860]

     

日期/时间:2015-08-05 15:53:08.265 -0600
  操作系统版本:Mac OS X 10.11(15A235d)
  报告版本:11

     

自启动以来的时间清醒:13000秒

     

坠毁线程:20

     

异常类型:EXC_BAD_ACCESS(SIGSEGV)
  例外代码:KERN_INVALID_ADDRESS位于0x000000000000008f
  例外注释:EXC_CORPSE_NOTIFY

     

VM区域接近0x8f:    - >       __TEXT 000000010ef62000-000000010ef63000 [4K] r-x / rwx SM = COW /Applications/Xcode.app/Contents/MacOS/Xcode

     

特定应用信息:
  ProductBuildVersion:6E35b

这是崩溃线程上的堆栈跟踪:

Thread 20 Crashed:: <DBGLLDBSessionThread (pid=6402)>
0   com.apple.LLDB.framework        0x0000000116b09ab4 swift::ArchetypeBuilder::resolveArchetype(swift::Type) + 68
1   com.apple.LLDB.framework        0x0000000116b0f808 std::__1::__function::__func<substConcreteTypesForDependentTypes(swift::ArchetypeBuilder&, swift::Type)::$_6, std::__1::allocator<substConcreteTypesForDependentTypes(swift::ArchetypeBuilder&, swift::Type)::$_6>, swift::Type (swift::Type)>::operator()(swift::Type&&) + 152
2   com.apple.LLDB.framework        0x0000000116bc0986 swift::Type::transform(std::__1::function<swift::Type (swift::Type)> const&) const + 54
3   com.apple.LLDB.framework        0x0000000116bc0f2b swift::Type::transform(std::__1::function<swift::Type (swift::Type)> const&) const + 1499
4   com.apple.LLDB.framework        0x0000000116bc0bbb swift::Type::transform(std::__1::function<swift::Type (swift::Type)> const&) const + 619
5   com.apple.LLDB.framework        0x0000000116bc0c0a swift::Type::transform(std::__1::function<swift::Type (swift::Type)> const&) const + 698
6   com.apple.LLDB.framework        0x0000000116b0c8f2 swift::ArchetypeBuilder::substDependentType(swift::Type) + 50
7   com.apple.LLDB.framework        0x0000000116e9554e (anonymous namespace)::LowerType::visitAnyStructType(swift::CanType, swift::StructDecl*) + 270
8   com.apple.LLDB.framework        0x0000000116e92e66 swift::Lowering::TypeConverter::getTypeLoweringForUncachedLoweredType(swift::Lowering::TypeConverter::TypeKey) + 150
9   com.apple.LLDB.framework        0x0000000116e92b39 swift::Lowering::TypeConverter::getTypeLowering(swift::Lowering::AbstractionPattern, swift::Type, unsigned int) + 2361
10  com.apple.LLDB.framework        0x0000000116f8f711 lldb_private::SwiftSILManipulator::emitLValueForVariable(swift::VarDecl*, lldb_private::SwiftExpressionParser::SILVariableInfo&) + 1521
11  com.apple.LLDB.framework        0x00000001172ac7ee (anonymous namespace)::LLDBNameLookup::emitLValueForVariable(swift::VarDecl*, swift::SILBuilder&) + 102
12  com.apple.LLDB.framework        0x0000000116ebb162 swift::Lowering::SILGenFunction::emitInitializationForVarDecl(swift::VarDecl*, swift::Type) + 98
13  com.apple.LLDB.framework        0x0000000116ebbc74 swift::ASTVisitor<(anonymous namespace)::InitializationForPattern, void, void, void, std::__1::unique_ptr<swift::Lowering::Initialization, std::__1::default_delete<swift::Lowering::Initialization> >, void, void>::visit(swift::Pattern*) + 404
14  com.apple.LLDB.framework        0x0000000116ebbc57 swift::ASTVisitor<(anonymous namespace)::InitializationForPattern, void, void, void, std::__1::unique_ptr<swift::Lowering::Initialization, std::__1::default_delete<swift::Lowering::Initialization> >, void, void>::visit(swift::Pattern*) + 375
15  com.apple.LLDB.framework        0x0000000116ebba0d swift::Lowering::SILGenFunction::visitPatternBindingDecl(swift::PatternBindingDecl*) + 45
16  com.apple.LLDB.framework        0x0000000116f0617c swift::Lowering::SILGenFunction::visitBraceStmt(swift::BraceStmt*) + 284
17  com.apple.LLDB.framework        0x0000000116ecd1c0 swift::Lowering::SILGenFunction::emitFunction(swift::FuncDecl*) + 320
18  com.apple.LLDB.framework        0x0000000116ea3966 swift::Lowering::SILGenModule::emitFunction(swift::FuncDecl*) + 246
19  com.apple.LLDB.framework        0x0000000116ea3828 swift::Lowering::SILGenModule::visitFuncDecl(swift::FuncDecl*) + 168
20  com.apple.LLDB.framework        0x0000000116ea579b swift::Lowering::SILGenModule::emitSourceFile(swift::SourceFile*, unsigned int) + 427
21  com.apple.LLDB.framework        0x0000000116ea5c22 swift::SILModule::constructSIL(swift::Module*, swift::SILOptions&, swift::SourceFile*, llvm::Optional<unsigned int>, bool, bool) + 386
22  com.apple.LLDB.framework        0x0000000116ea5d42 swift::performSILGeneration(swift::SourceFile&, swift::SILOptions&, llvm::Optional<unsigned int>, bool) + 98
23  com.apple.LLDB.framework        0x00000001172aa617 lldb_private::SwiftExpressionParser::Parse(lldb_private::Stream&, unsigned int, unsigned int, unsigned int) + 10715
24  com.apple.LLDB.framework        0x000000011706b3e8 lldb_private::ClangUserExpression::Parse(lldb_private::Stream&, lldb_private::ExecutionContext&, lldb_private::ExecutionPolicy, bool, unsigned int) + 1064
25  com.apple.LLDB.framework        0x000000011706cdb4 lldb_private::ClangUserExpression::Evaluate(lldb_private::ExecutionContext&, lldb_private::EvaluateExpressionOptions const&, char const*, char const*, lldb_private::SharingPtr<lldb_private::ValueObject>&, lldb_private::Error&, unsigned int, std::__1::shared_ptr<lldb_private::Module>*) + 628
26  com.apple.LLDB.framework        0x00000001171d1696 lldb_private::Target::EvaluateExpression(char const*, lldb_private::StackFrame*, lldb_private::SharingPtr<lldb_private::ValueObject>&, lldb_private::EvaluateExpressionOptions const&) + 376
27  com.apple.LLDB.framework        0x000000011716d75c lldb_private::SwiftLanguageRuntime::GetObjectDescription(lldb_private::Stream&, lldb_private::ValueObject&) + 668
28  com.apple.LLDB.framework        0x00000001170464e6 lldb_private::ValueObject::GetObjectDescription() + 370
29  com.apple.LLDB.framework        0x000000011548e228 lldb::SBValue::GetObjectDescription() + 76
30  com.apple.dt.dbg.DebuggerLLDB   0x00000001153f3c9e -[DBGLLDBDataValue _lldbValueObjectDescription] + 24
31  com.apple.dt.dbg.DebuggerLLDB   0x00000001153f3b7f -[DBGLLDBDataValue lldbDescription] + 29
32  com.apple.dt.dbg.DebuggerLLDB   0x00000001154023dc __87-[DBGLLDBSession printDescriptionOfDataValueToConsole:runAllThreads:completionHandler:]_block_invoke + 182
33  com.apple.dt.dbg.DebuggerLLDB   0x0000000115402e6d -[DBGLLDBSession handleNextActionWithState:withRunPending:] + 424
34  com.apple.dt.dbg.DebuggerLLDB   0x00000001153fdf44 DBGLLDBSessionThread(void*) + 980
35  libsystem_pthread.dylib         0x00007fff8ec12cb3 _pthread_body + 131
36  libsystem_pthread.dylib         0x00007fff8ec12c30 _pthread_start + 168
37  libsystem_pthread.dylib         0x00007fff8ec10419 thread_start + 13

似乎我们可能在这里处于新技术的最前沿,因为我还没有在这个问题上找到很多帮助。我想知道我们是否有某种导致编译时问题的异常配置,或者是否存在lldb可能崩溃的已知原因。在El Capitan,Yosemite,Xcode 6.3,Xcode 6.4等多台不同机器上也是如此。任何帮助表示赞赏!

2 个答案:

答案 0 :(得分:11)

我工作过,我正在积极开展可能比你大的项目(50多个图书馆,数百个拥有数千个LoC的自定义课程)。编译需要几秒钟,发布版本(2013年末MBP)最多需要2分钟,即使对于完整的Swift项目也是如此。

我强烈建议您查找其他原因,因为此选项告诉您的是您的问题是在其他地方,因为它会影响应用程序性能,而不会影响构建速度。也许你的.pch文件中充满了不属于那里的东西,它可能导致这种速度减慢。

其他有趣的事情是使用推理。我个人为每个变量声明类型,因为它更容易为其他变量阅读,但还有更多。由于推理可能变得复杂,它可能导致编译器花费大量时间来确定代码实际执行的操作。 Read this example article,虽然它更像是alpha问题。但也许,也许,你的代码中也有这样的东西。值得做的是尝试删除所有swift代码,编译库如果运行良好,那么你知道问题出在swift代码中,它可能与此有关。

另外,如果你提供什么实际上会减慢你的构建时间(因为你可以看到带有时间戳的整个构建过程,并且很可能只需要一步完成一步),它可以帮助更准确地找出问题。

希望它有所帮助!

编辑:Another article关于这个感兴趣的主题

答案 1 :(得分:8)

我设法在我们的项目中解决这个问题。 (总编译时间为12分钟)

关键是如您在SWIFT_WHOLE_MODULE_OPTIMIZATION = YES设置中所述设置user defined

但是你需要再做一次改变。您需要在调试中将优化级别设置为None,否则您将无法调试应用程序。

我在这里写了一篇关于它的博客文章:

https://tech.zalando.com/blog/improving-swift-compilation-times-from-12-to-2-minutes/