Tại sao thời gian biên dịch Swift lại chậm như vậy?


209

Tôi đang sử dụng Xcode 6 Beta 6.

Đây là một cái gì đó đã làm tôi khó chịu trong một thời gian, nhưng nó đạt đến điểm mà bây giờ nó hầu như không thể sử dụng được.

Dự án của tôi đang bắt đầu có kích thước khá gồm 65 tệp Swift và một vài tệp Objective-C được bắc cầu (đây thực sự không phải là nguyên nhân của vấn đề).

Có vẻ như bất kỳ sửa đổi nhỏ nào đối với bất kỳ tệp Swift nào (như thêm một khoảng trắng đơn giản trong một lớp hầu như không được sử dụng trong ứng dụng) sẽ khiến toàn bộ tệp Swift cho mục tiêu được chỉ định được biên dịch lại.

Sau khi điều tra sâu hơn, tôi đã thấy rằng những gì đang chiếm gần 100% thời gian của trình biên dịch là CompileSwiftgiai đoạn Xcode chạy swiftclệnh trên tất cả các tệp Swift của mục tiêu của bạn.

Tôi đã thực hiện một số điều tra thêm và nếu tôi chỉ giữ đại biểu ứng dụng với bộ điều khiển mặc định thì quá trình biên dịch rất nhanh, nhưng khi tôi thêm ngày càng nhiều tệp dự án của mình, thời gian biên dịch bắt đầu rất chậm.

Bây giờ chỉ với 65 tệp nguồn, phải mất khoảng 8/10 giây để biên dịch mỗi lần. Không nhanh lắm đâu .

Tôi chưa thấy bài đăng nào nói về vấn đề này ngoại trừ bài này , nhưng đây là phiên bản cũ của Xcode 6. Vì vậy, tôi tự hỏi liệu tôi có phải là người duy nhất trong trường hợp đó không.

CẬP NHẬT

Tôi đã kiểm tra một vài dự án Swift trên GitHub như Alamofire , EulerCryptoSwift , nhưng không ai trong số họ có đủ tệp Swift để thực sự so sánh. Dự án duy nhất tôi thấy bắt đầu có kích thước kháSwiftHN và mặc dù chỉ có một tá tệp nguồn, tôi vẫn có thể xác minh điều tương tự, một không gian đơn giản và toàn bộ dự án cần biên dịch lại bắt đầu thực hiện thời gian ít (2/3 giây).

So với mã Objective-C nơi cả bộ phân tích và biên dịch đều phát sáng nhanh, điều này thực sự có cảm giác như Swift sẽ không bao giờ có thể xử lý các dự án lớn, nhưng xin vui lòng cho tôi biết tôi đã sai.

CẬP NHẬT Với Xcode 6 Beta 7

Vẫn không có cải thiện gì. Điều này đang bắt đầu trở nên vô lý. Với việc thiếu #importSwift, tôi thực sự không thấy Apple sẽ có thể tối ưu hóa điều này như thế nào.

CẬP NHẬT Với Xcode 6.3 và Swift 1.2

Apple đã thêm các bản dựng gia tăng (và nhiều tối ưu hóa trình biên dịch khác). Bạn phải di chuyển mã của mình sang Swift 1.2 để thấy những lợi ích đó, nhưng Apple đã thêm một công cụ trong Xcode 6.3 để giúp bạn làm như vậy:

Nhập mô tả hình ảnh ở đây

TUY NHIÊN

Đừng vui mừng quá nhanh như tôi đã làm. Trình giải đồ thị mà họ sử dụng để làm cho bản dựng gia tăng chưa được tối ưu hóa tốt.

Thật vậy, trước tiên, nó không xem xét các thay đổi chữ ký hàm, vì vậy nếu bạn thêm một khoảng trắng trong khối của một phương thức, tất cả các tệp tùy thuộc vào lớp đó sẽ được biên dịch lại.

Thứ hai, nó dường như tạo cây dựa trên các tệp được biên dịch lại ngay cả khi thay đổi không ảnh hưởng đến chúng. Ví dụ, nếu bạn di chuyển ba lớp này vào các tệp khác nhau

class FileA: NSObject {
    var foo:String?
}
class FileB: NSObject {
    var bar:FileA?
}
class FileC: NSObject {
    var baz:FileB?
}

Bây giờ nếu bạn sửa đổi FileA, trình biên dịch rõ ràng sẽ đánh dấu FileAđể được biên dịch lại. Nó cũng sẽ biên dịch lại FileB(điều đó sẽ ổn dựa trên các thay đổi FileA), nhưng cũng FileCFileBđược biên dịch lại, và điều đó khá tệ vì FileCkhông bao giờ sử dụng FileAở đây.

Vì vậy, tôi hy vọng họ cải thiện bộ giải cây phụ thuộc đó ... Tôi đã mở một radar với mã mẫu này.

CẬP NHẬT Với Xcode 7 beta 5 và Swift 2.0

Hôm qua Apple đã phát hành bản beta 5 và bên trong các ghi chú phát hành mà chúng ta có thể thấy:

Swift Language & Compiler • Các bản dựng tăng dần: chỉ thay đổi phần thân của hàm sẽ không còn khiến các tệp phụ thuộc được xây dựng lại. (15352929)

Tôi đã thử nó và tôi phải nói rằng nó đang hoạt động thực sự (thực sự!). Họ đã tối ưu hóa rất nhiều các bản dựng gia tăng nhanh chóng.

Tôi thực sự khuyên bạn nên tạo một swift2.0nhánh và giữ cho mã của mình được cập nhật bằng XCode 7 beta 5. Bạn sẽ hài lòng bởi các cải tiến của trình biên dịch (tuy nhiên tôi muốn nói rằng trạng thái toàn cầu của XCode 7 vẫn chậm và lỗi)

CẬP NHẬT Với Xcode 8.2

Đã được một thời gian kể từ lần cập nhật cuối cùng của tôi về vấn đề này.

Ứng dụng của chúng tôi hiện có khoảng 20 nghìn dòng mã Swift gần như độc quyền, khá tốt nhưng không nổi bật. Nó đã trải qua swift 2 và hơn 3 di chuyển nhanh chóng. Phải mất khoảng 5 / 6m để biên dịch trên Macbook pro giữa năm 2014 (Intel Core i7 2,5 GHz), ổn trên bản dựng sạch.

Tuy nhiên, bản dựng gia tăng vẫn là một trò đùa mặc dù Apple tuyên bố rằng:

Xcode sẽ không xây dựng lại toàn bộ mục tiêu khi chỉ có những thay đổi nhỏ xảy ra. (28892485)

Rõ ràng tôi nghĩ rằng nhiều người trong chúng ta chỉ cười sau khi kiểm tra tài sản vô nghĩa này (thêm một tài sản riêng tư (riêng tư!) Vào bất kỳ tệp nào trong dự án của tôi sẽ biên dịch lại toàn bộ ...)

Tôi muốn chỉ cho các bạn biết chủ đề này trên các diễn đàn của nhà phát triển Apple có thêm một số thông tin về vấn đề này (cũng như đánh giá cao thông tin liên lạc của nhà phát triển Apple về vấn đề này một lần nữa)

Về cơ bản mọi người đã nghĩ ra một vài điều để cố gắng cải thiện việc xây dựng gia tăng:

  1. Thêm một HEADER_MAP_USES_VFSthiết lập dự án được đặt thànhtrue
  2. Vô hiệu hóa Find implicit dependenciestừ chương trình của bạn
  3. Tạo một dự án mới và di chuyển hệ thống phân cấp tệp của bạn sang dự án mới.

Tôi sẽ thử giải pháp 3 nhưng giải pháp 1/2 không hiệu quả với chúng tôi.

Điều đáng buồn cười trong toàn bộ tình huống này là khi nhìn vào bài đăng đầu tiên về vấn đề này, chúng tôi đã sử dụng Xcode 6 với mã tin swift 1 hoặc swift 1.1 khi chúng tôi đạt được sự chậm chạp trong quá trình biên dịch đầu tiên và bây giờ khoảng hai năm sau mặc dù đã có những cải tiến thực sự từ Apple tình hình cũng tệ như với Xcode 6. Thật mỉa mai.

Tôi thực sự hối tiếc vì đã chọn Swift trên Obj / C cho dự án của chúng tôi vì sự thất vọng hàng ngày mà nó liên quan. (Tôi thậm chí chuyển sang AppCode nhưng đó là một câu chuyện khác)

Dù sao tôi thấy bài đăng SO này có 32k lượt xem và 143 lượt viết khi viết bài này nên tôi đoán tôi không phải là người duy nhất. Các bạn ơi, mặc dù có bi quan về tình huống này, có thể có một chút ánh sáng ở cuối đường hầm.

Nếu bạn có thời gian (và can đảm!) Tôi đoán Apple hoan nghênh radar về điều này.

Đến lần sau! Chúc mừng

CẬP NHẬT Với Xcode 9

Tình cờ gặp điều này ngày hôm nay. Xcode lặng lẽ giới thiệu một hệ thống xây dựng mới để cải thiện hiệu suất khủng khiếp hiện tại. Bạn phải kích hoạt nó thông qua các cài đặt không gian làm việc.

nhập mô tả hình ảnh ở đây

Đã thử chưa nhưng sẽ cập nhật bài này sau khi hoàn thành. Có vẻ đầy hứa hẹn mặc dù.


1
Hấp dẫn! Tôi tự hỏi nếu nó chỉ là một tối ưu hóa bị thiếu hoặc cần phải phân tích quá nhiều tệp vì không có tệp giao diện.
zaph

2
Có vấn đề tương tự, và cuối cùng tôi nhận ra rằng đó là do các toán tử tùy chỉnh được sử dụng trong các lớp thực thể để giải tuần tự hóa từ JSON. Nếu bạn đang sử dụng bất kỳ, tôi khuyên bạn nên thử chuyển đổi chức năng bình thường từng cái một và xem có gì thay đổi không.
Antonio

4
Quá trình biên dịch đã trở nên chậm chạp trong dự án của tôi kể từ XCode 6 beta 6. Tôi không chắc là do thay đổi trong bản beta hay do mã của tôi. Nhưng dự án của tôi thậm chí còn chưa lớn (~ 40-50 tệp Swift).
Cầu lôngCat

2
Biên dịch đã trở nên chậm không chịu nổi khi dự án của tôi đã phát triển. Tôi cũng phụ thuộc vào một số nhóm, mà tôi chắc chắn sẽ giải quyết vấn đề này. Điều này đang sử dụng bản phát hành không beta gần đây.
Andy

2
Việc xây dựng gia tăng vẫn được thực hiện trong một "phân tích phụ thuộc bảo thủ, do đó bạn vẫn có thể thấy việc xây dựng lại nhiều tệp hơn là hoàn toàn cần thiết." Hy vọng, nó sẽ cải thiện theo thời gian.
nmdias 23/2/2015

Câu trả lời:


70

Chà, hóa ra Rob Napier đã đúng. Đó là một tệp duy nhất (thực tế là một phương thức) đã khiến trình biên dịch bị lỗi.

Bây giờ đừng hiểu lầm tôi. Swift không biên dịch lại tất cả các tệp của bạn mỗi lần, nhưng điều tuyệt vời bây giờ là Apple đã thêm phản hồi biên dịch theo thời gian thực qua các tệp mà nó biên dịch, vì vậy Xcode 6 GM hiện cho thấy các tệp Swift đang được biên dịch và trạng thái biên dịch trong thời gian thực như bạn có thể thấy trong ảnh chụp màn hình này:

Nhập mô tả hình ảnh ở đây

Vì vậy, điều này rất tiện lợi để biết tập tin nào của bạn mất quá nhiều thời gian. Trong trường hợp của tôi, đó là đoạn mã này:

var dic = super.json().mutableCopy() as NSMutableDictionary
dic.addEntriesFromDictionary([
        "url" : self.url?.absoluteString ?? "",
        "title" : self.title ?? ""
        ])

return dic.copy() as NSDictionary

bởi vì tài sản titlelà loại var title:String?và không NSString. Trình biên dịch đã phát điên khi thêm nó vào NSMutableDictionary.

Thay đổi nó thành:

var dic = super.json().mutableCopy() as NSMutableDictionary
dic.addEntriesFromDictionary([
        "url" : self.url?.absoluteString ?? "",
        "title" : NSString(string: self.title ?? "")
        ])

return dic.copy() as NSDictionary

làm cho quá trình biên dịch đi từ 10/15 giây (thậm chí nhiều hơn) xuống còn một giây ... thật tuyệt vời.


3
Cảm ơn đã theo dõi với câu trả lời. Điều này có thể rất hữu ích cho những người khác đang theo đuổi ở đó công cụ suy luận kiểu bị sa lầy trong quá trình biên dịch.
Rob Napier

1
Nơi mà bạn có được quan điểm này @apouche? Tôi không thấy nó trong xcode
Eric

2
Bạn cần mở trợ lý gỡ lỗi (CMD + 8) và nhấp vào bản dựng hiện tại
apouche

1
vâng tôi chắc chắn rằng Apple sẽ tối ưu hóa điều này sau này, nếu không thì các dự án trong thế giới thực trong swift sẽ bị tiêu diệt ngay tại đây.
apouche

1
Làm cách nào tôi có thể truy cập công cụ này để hiển thị các tệp đang được biên dịch?
jgvb

41

Chúng tôi đã thử khá nhiều thứ để chống lại điều này khi chúng tôi có khoảng 100 nghìn dòng mã Swift và 300 nghìn dòng mã ObjC.

Bước đầu tiên của chúng tôi là tối ưu hóa tất cả các chức năng theo đầu ra thời gian biên dịch hàm (ví dụ như được mô tả ở đây https://thatthinginswift.com/debug-long-compile-times-swift/ )

Tiếp theo, chúng tôi đã viết một tập lệnh để hợp nhất tất cả các tệp nhanh chóng vào một tệp, điều này phá vỡ các cấp truy cập nhưng nó mang lại thời gian biên dịch của chúng tôi từ 5-6 phút đến ~ 1 phút.

Điều này hiện không còn tồn tại vì chúng tôi đã hỏi Apple về điều này và họ khuyên chúng tôi nên làm như sau:

  1. Bật 'tối ưu hóa toàn bộ mô-đun' trong cài đặt 'Trình biên dịch Swift - Tạo mã'. Lựa chọn'Fast, Whole Module Optimization'

nhập mô tả hình ảnh ở đây

  1. Trong 'Trình biên dịch Swift - Cờ tùy chỉnh', để xây dựng phát triển của bạn, hãy thêm '-Onone'

nhập mô tả hình ảnh ở đây nhập mô tả hình ảnh ở đây

Khi các cờ này được đặt, trình biên dịch sẽ biên dịch tất cả các tệp Swift trong một bước. Chúng tôi đã tìm thấy với tập lệnh hợp nhất của mình, điều này nhanh hơn nhiều so với việc biên dịch các tệp riêng lẻ. Tuy nhiên, không có ' -Onone'ghi đè, nó cũng sẽ tối ưu hóa toàn bộ mô-đun, tốc độ chậm hơn. Khi chúng tôi đặt '-Onone'cờ trong các cờ Swift khác, nó sẽ dừng tối ưu hóa, nhưng nó không dừng biên dịch tất cả các tệp Swift trong một bước.

Để biết thêm thông tin về tối ưu hóa toàn bộ mô-đun, hãy xem bài đăng trên blog của Apple tại đây - https://swift.org/blog/whole-module-optimizes/

Chúng tôi đã tìm thấy các cài đặt này cho phép mã Swift của chúng tôi biên dịch trong 30 giây :-) Tôi không có bằng chứng về cách nó sẽ hoạt động trên các dự án khác, nhưng tôi khuyên bạn nên thử nếu thời gian biên dịch Swift vẫn là một vấn đề đối với bạn.

Lưu ý đối với các bản dựng cửa hàng Ứng dụng của bạn, bạn nên bỏ '-Onone'cờ ra, vì tối ưu hóa được khuyến nghị cho các bản dựng sản xuất.


4
Cảm ơn rất nhiều vì lời khuyên này! Tôi chỉ đơn giản là không hiểu tại sao không có gì giống như vậy trong các nguồn chính thức (ít nhất là dễ tìm), ví dụ như bài báo bạn đề cập nên (phải!) Có nhận xét về -Onone. Hiện tại chúng tôi không thể sử dụng tối ưu hóa toàn bộ mô-đun vì nó làm cho trình biên dịch bị sập ... Nhưng lời khuyên của bạn giúp tăng tốc độ x10 cho tốc độ xây dựng của chúng tôi. Trên MacBook Air (năm 2013), nó đã được xây dựng khoảng 8 phút, bây giờ chỉ còn khoảng 1 phút rưỡi thời gian mà nó dành để chuyển đổi giữa các mục tiêu (chúng tôi có ứng dụng, tiện ích mở rộng và một số khung trong nhà) và biên dịch các câu chuyện
Ilya Puchka

Tôi cũng đã thử nghiệm phương pháp này và nó chỉ là phương pháp được đề cập bao gồm -Onone và nó làm giảm đáng kể thời gian xây dựng.
Vlad

Làm việc với tôi cũng vậy. Sử dụng -Ononetrợ giúp để giảm thời gian xây dựng. Cảm ơn rất nhiều bạn đời!
nahung89

34

Nó có thể có ít liên quan đến quy mô của dự án của bạn. Đây có thể là một số đoạn mã cụ thể, thậm chí có thể chỉ là một dòng. Bạn có thể kiểm tra điều này bằng cách cố gắng biên dịch một tệp tại một thời điểm chứ không phải toàn bộ dự án. Hoặc thử xem nhật ký xây dựng để xem tệp nào mất quá nhiều thời gian.

Như một ví dụ về các loại mã có thể gây rắc rối, ý chính 38 dòng này mất hơn một phút để biên dịch trong beta7. Tất cả nguyên nhân là do một khối này gây ra:

let pipeResult =
seq |> filter~~ { $0 % 2 == 0 }
  |> sorted~~ { $1 < $0 }
  |> map~~ { $0.description }
  |> joinedWithCommas

Đơn giản hóa điều đó chỉ bằng một hoặc hai dòng và nó biên dịch gần như ngay lập tức. Vấn đề là một cái gì đó về điều này đang gây ra sự tăng trưởng theo cấp số nhân (có thể là tăng trưởng giai thừa) trong trình biên dịch. Rõ ràng điều đó không lý tưởng, và nếu bạn có thể cách ly những tình huống như vậy, bạn nên mở radar để giúp giải quyết những vấn đề đó.


Tôi không chắc bạn đã thấy bình luận của tôi về CompileSwiftgiai đoạn này. Phải mất tất cả các tệp nhanh chóng ngay cả khi chỉ có một sửa đổi. Vì vậy, nếu đó là một tệp đang mất một thời gian (mà tôi rất nghi ngờ), trình biên dịch sẽ không bao giờ cho bạn biết đó là tệp nào.
apouche

10
Bạn có thể biên dịch các tệp riêng lẻ bằng cách sử dụng swiftcđể xem chúng mất bao lâu.
Rob Napier

Tôi xin lỗi vì đã không cho bạn tiền thưởng vì tôi không tin vào lúc đầu. Tôi cũng đã cố gắng biên dịch từng tệp một nhưng nó rất khó thực hiện (phải đưa ra các khung công tác và deps mỗi lần) vì vậy tôi đã từ bỏ. Vui lòng xem câu trả lời mới nhất của tôi cho bài đăng này để được giải thích đầy đủ
apouche

Tôi không nghĩ đó là quy mô dự án. Dự án của tôi chỉ có 4 tệp nhanh chóng và đột nhiên bắt đầu biên dịch cực kỳ chậm. Nó đã được chiếu sáng nhanh ngày hôm qua. Không thể đặt ngón tay của tôi vào bất cứ điều gì tôi đã làm cho dự án của tôi nói riêng ngoại trừ thêm biểu tượng và khởi chạy hình ảnh.
Travis M.

33

Nếu bạn đang cố gắng xác định các tệp cụ thể làm chậm thời gian biên dịch của mình, bạn có thể thử biên dịch nó từ dòng lệnh của mình thông qua xctool sẽ cung cấp cho bạn thời gian biên dịch tệp theo tệp.

Điều cần lưu ý là, theo mặc định, nó xây dựng đồng thời 2 tệp cho mỗi lõi CPU và sẽ không cung cấp cho bạn thời gian trôi qua "mạng", mà là thời gian "người dùng" tuyệt đối. Bằng cách này, tất cả các định thời ngay cả giữa các tệp song song và trông rất giống nhau.

Để khắc phục điều này, hãy đặt -jobscờ thành 1 , để nó không song song hóa các bản dựng tệp. Sẽ mất nhiều thời gian hơn, nhưng cuối cùng, bạn sẽ có thời gian biên dịch "mạng" mà bạn có thể so sánh tệp theo tệp.

Đây là một lệnh ví dụ nên thực hiện thủ thuật:

xctool -workspace <your_workspace> -scheme <your_scheme> -jobs 1 build

Đầu ra của giai đoạn "Biên dịch tệp Swift" sẽ giống như:

...Compile EntityObserver.swift (1623 ms)Compile Session.swift (1526 ms)Compile SearchComposer.swift (1556 ms)
...

Từ đầu ra này, bạn có thể nhanh chóng xác định tệp nào đang mất nhiều thời gian hơn các tệp khác để biên dịch. Hơn nữa, bạn có thể xác định với độ chính xác cao xem liệu cấu trúc lại của bạn (phôi rõ ràng, gợi ý loại, v.v ...) có giảm thời gian biên dịch cho các tệp cụ thể hay không.

LƯU Ý: về mặt kỹ thuật bạn cũng có thể làm điều đó với xcodebuildnhưng đầu ra rất dài và khó tiêu thụ.


1
Chỉ cần đảm bảo rằng bạn đã đặt Tối ưu hóa toàn bộ mô-đun của dự án thành sai, hoặc nó sẽ không tách rời các tệp nhanh chóng riêng lẻ.
sabes

1
Xem Swift CompilerOptimization LevelchoFast, Whole Module Optimization [-O -whole-module-optimization]
Matt

26

Trong trường hợp của tôi, Xcode 7 không có sự khác biệt nào cả. Tôi đã có nhiều hàm cần vài giây để biên dịch.

Thí dụ

// Build time: 5238.3ms
return CGSize(width: size.width + (rightView?.bounds.width ?? 0) + (leftView?.bounds.width ?? 0) + 22, height: bounds.height)

Sau khi hủy bỏ các tùy chọn, thời gian xây dựng giảm 99,4% .

// Build time: 32.4ms
var padding: CGFloat = 22
if let rightView = rightView {
    padding += rightView.bounds.width
}

if let leftView = leftView {
    padding += leftView.bounds.width
}
return CGSizeMake(size.width + padding, bounds.height)

Xem thêm ví dụ trong bài nàybài này .

Xây dựng phân tích thời gian cho Xcode

Tôi đã phát triển một trình cắm Xcode có thể hữu ích cho bất kỳ ai gặp phải những vấn đề này.

hình ảnh

Dường như có những cải tiến sắp tới trong Swift 3, vì vậy hy vọng chúng ta sẽ thấy mã Swift của chúng tôi biên dịch nhanh hơn sau đó.


Tuyệt vời, Hy vọng tôi có thể cung cấp cho bạn nhiều hơn +1. bạn đúng và plugin của bạn cũng rất tuyệt Tôi đã sử dụng nó và thời gian xây dựng của tôi đang bị giảm, điều đó có nghĩa là sự phát triển siêu nhanh bởi vì các tùy chọn này đôi khi là cơn ác mộng và khiến trình biên dịch bị chậm.
hardikdevios

Tuyệt diệu ! Công cụ của bạn giúp tôi rất nhiều. Cảm ơn
Phil

Plugin tuyệt vời - Thực sự hữu ích! Cảm ơn
365SplendidSun 16/07/2016

@Robert Gummesson, chúng ta có công cụ nào cho Mã khách quan không?
Ashok

19

Có lẽ chúng ta không thể sửa trình biên dịch Swift, nhưng thứ chúng ta có thể sửa là mã của chúng ta!

Có một tùy chọn ẩn trong trình biên dịch Swift in ra các khoảng thời gian chính xác mà trình biên dịch cần để biên dịch mọi hàm duy nhất : -Xfrontend -debug-time-function-bodies. Nó cho phép chúng tôi tìm ra các nút cổ chai trong mã của chúng tôi và cải thiện đáng kể thời gian biên dịch.

Đơn giản chạy sau trong thiết bị đầu cuối và phân tích kết quả:

xcodebuild -workspace App.xcworkspace -scheme App clean build OTHER_SWIFT_FLAGS="-Xfrontend -debug-time-function-bodies" | grep [1-9].[0-9]ms | sort -nr > culprits.txt

Tuyệt vời Brian Irace đã viết bài viết tuyệt vời về nó Hồ sơ thời gian biên dịch Swift của bạn .


2
Đối với những người có zsh alias grep='noglob grep'trước, othewise grep sẽ không hoạt động
Jaime Agudo

16

Giải pháp là đúc.

Tôi đã có một loạt các từ điển lớn, như thế này:

["title" : "someTitle", "textFile" : "someTextFile"],
["title" : "someTitle", "textFile" : "someTextFile"],
["title" : "someTitle", "textFile" : "someTextFile"],
["title" : "someTitle", "textFile" : "someTextFile"],
.....

Mất khoảng 40 phút để biên dịch nó. Cho đến khi tôi bỏ từ điển như thế này:

["title" : "someTitle", "textFile" : "someTextFile"] as [String : String],
["title" : "someTitle", "textFile" : "someTextFile"] as [String : String],
["title" : "someTitle", "textFile" : "someTextFile"] as [String : String],
....

Điều này hoạt động cho hầu hết các vấn đề khác mà tôi gặp phải liên quan đến các loại dữ liệu mà tôi đã mã hóa cứng vào ứng dụng của mình.


6
vâng, đó là một phần của những tối ưu hóa bạn làm để cải thiện thời gian biên dịch, nhưng vẫn là vấn đề chính với trình biên dịch swift hiện tại, là nó vẫn biên dịch lại mọi thứ tập tin swift mỗi khi bạn thực hiện sửa đổi nhỏ nhất.
apouche 2/2/2015

4
Điều đó sẽ buồn cười nếu nó không quá buồn.
Tom Andersen

15

Một điều cần lưu ý là công cụ suy luận kiểu Swift có thể rất chậm với các kiểu lồng nhau. Bạn có thể có được một ý tưởng chung về những gì gây ra sự chậm chạp bằng cách xem nhật ký xây dựng cho các đơn vị biên dịch riêng lẻ mất nhiều thời gian và sau đó sao chép và dán toàn bộ lệnh sinh ra Xcode vào cửa sổ Terminal và sau đó nhấn CTRL- \ để nhận một số chẩn đoán. Hãy xem http://blog.impathic.com/post/99647568844/debugging-slow-swift-compile-times để biết ví dụ đầy đủ.


Đó là cho tôi câu trả lời tốt nhất (xem liên kết). Tôi có thể DỄ DÀNG tìm thấy hai dòng khác nhau là một vấn đề và giải quyết nó bằng cách phân tách các dòng của tôi thành các dòng nhỏ hơn.
Nico

Đó là một câu trả lời rất hữu ích vì nó cho thấy làm thế nào để tìm trình biên dịch phát điên. Trong trường hợp của tôi, đó là: ', kết quả là "biểu thức quá phức tạp để được giải quyết trong thời gian hợp lý; xem xét chia biểu thức thành các biểu thức phụ riêng biệt"
Dmitry

Đây chắc chắn là cách hữu ích nhất để giải quyết vấn đề này.
Richard Venable

9

Đồng thời đảm bảo rằng khi biên dịch để gỡ lỗi (Swift hoặc Objective-C), bạn đặt thành Chỉ xây dựng kiến ​​trúc hoạt động:

nhập mô tả hình ảnh ở đây


6

Vì tất cả những thứ này đều ở bản Beta và vì trình biên dịch Swift (ít nhất là cho đến ngày hôm nay) không mở, tôi đoán không có câu trả lời thực sự cho câu hỏi của bạn.

Trước hết, so sánh Objective-C với trình biên dịch Swift bằng cách nào đó thật tàn nhẫn. Swift vẫn đang trong giai đoạn Beta và tôi chắc chắn Apple đang làm việc trong việc cung cấp chức năng và sửa lỗi, hơn là cung cấp tốc độ cực nhanh (bạn không bắt đầu xây nhà bằng cách mua đồ nội thất). Tôi đoán Apple sẽ tối ưu hóa trình biên dịch trong thời gian tới.

Nếu vì một lý do nào đó, tất cả các tệp nguồn phải được biên dịch hoàn thành, một tùy chọn có thể là tạo các mô-đun / thư viện riêng biệt. Nhưng tùy chọn này vẫn chưa thể thực hiện được, vì Swift không thể cho phép các thư viện cho đến khi ngôn ngữ ổn định.

Tôi đoán là họ sẽ tối ưu hóa trình biên dịch. Vì lý do tương tự mà chúng ta không thể tạo các mô-đun được biên dịch trước, đó cũng có thể là trình biên dịch cần biên dịch mọi thứ từ đầu. Nhưng một khi ngôn ngữ đạt đến phiên bản ổn định và định dạng của nhị phân không thay đổi nữa, chúng tôi sẽ có thể tạo thư viện của mình và có thể (?) Trình biên dịch cũng sẽ có thể tối ưu hóa công việc của nó.

Tuy nhiên, chỉ cần đoán, chỉ có Apple biết ...


"Vì lý do tương tự mà chúng tôi không thể tạo các mô-đun được biên dịch trước, đó cũng có thể là trình biên dịch cần biên dịch mọi thứ từ đầu." quan sát tốt, không nghĩ về nó theo cách đó trước đây.
chakrit

1
2017 và nó vẫn chậm
Pedro Paulo Amorim

2017 với Xcode 9 và hệ thống xây dựng mới và vẫn chậm
pableiros

Năm 2018 với Xcode 9, tôi có một dự án với hơn 50 tệp swift, nếu tôi thực hiện xây dựng sạch, giờ đây đã trôi qua được 5 phút và quá trình biên dịch của tôi chưa hoàn thành.
Chen Li Yong

5

Đối với Xcode 8, hãy chuyển đến cài đặt dự án, sau đó Trình chỉnh sửa> Thêm cài đặt xây dựng> Thêm cài đặt do người dùng xác định và thêm vào như sau:

SWIFT_WHOLE_MODULE_OPTIMIZATION = YES

Thêm cờ này đã giảm thời gian biên dịch xây dựng sạch của chúng tôi từ 7 phút xuống còn 65 giây cho một dự án nhanh chóng 40KLOC, thật kỳ diệu. Cũng có thể xác nhận 2 người bạn đã thấy những cải tiến tương tự trong các dự án doanh nghiệp.

Tôi chỉ có thể giả sử đây là một loại lỗi trong Xcode 8.0

EDIT: Nó dường như không còn hoạt động nữa trong Xcode 8.3 đối với một số người.


2
Xin vui lòng "cài đặt dự án" ở đâu?
Raniys

@Raniys Nhấp vào biểu tượng màu xanh ở cấp gốc trong khung bên trái trong Xcode.
Chris

Tôi thấy rằng kể từ Xcode 8.3 (không phải beta), điều này không còn hoạt động trong trường hợp của tôi :(
Chris

4

Thật không may, trình biên dịch Swift vẫn chưa được tối ưu hóa để biên dịch nhanh và tăng dần (kể từ Xcode 6.3 beta). Trong khi đó, bạn có thể sử dụng một số kỹ thuật sau để cải thiện thời gian biên dịch Swift:

  • Chia ứng dụng thành các Khung để giảm tác động biên dịch lại. Nhưng hãy lưu ý rằng bạn phải tránh phụ thuộc theo chu kỳ trong ứng dụng của mình. Để biết thêm thông tin về chủ đề này, hãy kiểm tra bài đăng này: http://bits.citrusbyte.com/improving-swift-compile-time/

  • Sử dụng Swift cho các phần trong dự án của bạn khá ổn định và không thay đổi thường xuyên. Đối với các khu vực khác mà bạn cần thay đổi rất thường xuyên hoặc các khu vực yêu cầu nhiều lần lặp biên dịch / chạy để hoàn thành (hầu hết mọi nội dung liên quan đến giao diện người dùng), hãy sử dụng Objective-C tốt hơn với cách tiếp cận kết hợp.

  • Hãy thử tiêm mã thời gian chạy với 'Tiêm cho Xcode'

  • Sử dụng phương pháp roopc: http://roopc.net/posts/2014/speeding-up-swift-builds/

  • Làm giảm động cơ suy luận kiểu nhanh bằng cách đưa ra một số gợi ý với các diễn viên rõ ràng.


4

Xây dựng mảng và từ điển Swift dường như là một nguyên nhân khá phổ biến cho việc này (đặc biệt đối với bạn đến từ nền tảng Ruby ), nghĩa là,

var a = ["a": "b",
         "c": "d",
         "e": "f",
         "g": "h",
         "i": "j",
         "k": "l",
         "m": "n",
         "o": "p",
         "q": "r",
         "s": "t",
         "u": "v",
         "x": "z"]

có lẽ sẽ là nguyên nhân mà điều này sẽ khắc phục nó:

var a = NSMutableDictionary()
a["a"] = "b"
a["c"] = "d"
... and so on

4

Để gỡ lỗi và kiểm tra, hãy đảm bảo sử dụng các cài đặt sau để giảm thời gian biên dịch từ khoảng 20 phút xuống dưới 2 phút,

  1. Trong cài đặt xây dựng dự án, tìm kiếm "Tối ưu hóa" Biến Gỡ lỗi thành "Nhanh nhất [-O3]" trở lên.
  2. Đặt Build cho Active Architecture: CÓ
  3. Định dạng thông tin gỡ lỗi: DWARF
  4. Tối ưu hóa toàn bộ mô-đun: KHÔNG

Tôi đã lãng phí vô số thời gian chờ đợi dự án được xây dựng chỉ để nhận ra rằng tôi phải thực hiện một thay đổi nhỏ đó và phải chờ thêm 30 phút nữa để kiểm tra nó. Đây là các cài đặt làm việc cho tôi. (Tôi vẫn đang thử nghiệm cài đặt)

Tuy nhiên, hãy đảm bảo bạn ít nhất đặt "DWARF với dSYM" (nếu bạn muốn giám sát ứng dụng của mình) và Build Active Architecture thành "KHÔNG" để phát hành / Lưu trữ để đẩy lên iTunes Connect (tôi cũng nhớ lãng phí vài giờ ở đây).


4
Tôi có thể sai, nhưng sẽ không thiết lập mức tối ưu hóa tăng thực sự làm tăng thời gian xây dựng? Các mức tối ưu hóa sẽ cải thiện hiệu suất thời gian chạy.
Thác Michael

1
Set Build for Active Architecture: YESđã cho tôi giảm khoảng 45% thời gian biên dịch. Cảm ơn nhiều.
Jean Le Moignan

4

Trình biên dịch dành nhiều thời gian để suy luận và kiểm tra các loại. Vì vậy, việc thêm chú thích loại giúp trình biên dịch rất nhiều.

Nếu bạn có nhiều cuộc gọi chức năng chuỗi như

let sum = [1,2,3].map({String($0)}).flatMap({Float($0)}).reduce(0, combine: +)

Sau đó, trình biên dịch sẽ mất một lúc để tìm ra loại sumnên là gì. Thêm các loại giúp. Điều gì cũng giúp là kéo các bước không liên tục thành các biến riêng biệt.

let numbers: [Int] = [1,2,3]
let strings: [String] = sum.map({String($0)})
let floats: [Float] = strings.flatMap({Float($0)})
let sum: Float = floats.reduce(0, combine: +)

Đặc biệt đối với các loại số CGFloat, Intnó có thể giúp rất nhiều. Một số bằng chữ 2có thể đại diện cho nhiều loại số khác nhau. Vì vậy, trình biên dịch cần phải tìm ra từ bối cảnh đó là một.

Các chức năng mất nhiều thời gian để tìm kiếm như thế nào +cũng nên tránh. Việc sử dụng một số +để ghép nối một số mảng là chậm vì trình biên dịch cần phải tìm ra cách thực hiện nào +nên được gọi cho mỗi mảng +. Vì vậy, sử dụng một var a: [Foo]với append()thay thế nếu có thể.

Bạn có thể thêm cảnh báo để phát hiện các chức năng nào được biên dịch chậm trong Xcode .

Trong Cài đặt bản dựng cho tìm kiếm mục tiêu của bạn cho các cờ Swift khác và thêm

-Xfrontend -warn-long-function-bodies=100

để cảnh báo cho mọi hàm mất hơn 100 ms để biên dịch.


4

Đối với các dự án mà trộn Objective-C và Swift code, chúng ta có thể thiết lập -enable-bridging-pchtrong Other Swift Flags. Với điều này, tiêu đề bắc cầu chỉ được phân tích cú pháp một lần và kết quả (một tệp tiêu đề được biên dịch trước tạm thời của bộ dữ liệu đã được lưu lại và được sử dụng lại trên tất cả các tệp Swift trong mục tiêu. Apple tuyên bố họ giảm 30% thời gian xây dựng. Liên kết tham khảo:

LƯU Ý: Điều này chỉ hoạt động cho Swift 3.1 trở lên.


2

Khởi động lại máy Mac của tôi đã làm điều kỳ diệu cho vấn đề này. Tôi đã chuyển từ bản dựng 15 phút sang bản dựng 30 giây chỉ bằng cách khởi động lại.


1

Thời gian biên dịch Swift được cải thiện trong Xcode mới 6.3

Cải tiến trình biên dịch

Trình biên dịch Swift 1.2 được thiết kế để ổn định hơn và cải thiện hiệu suất theo mọi cách. Những thay đổi này cũng cung cấp trải nghiệm tốt hơn khi làm việc với Swift trong Xcode. Một số cải tiến dễ thấy nhất bao gồm:

Xây dựng gia tăng

Các tệp nguồn không thay đổi sẽ không còn được biên dịch lại theo mặc định, điều này sẽ cải thiện đáng kể thời gian xây dựng cho hầu hết các trường hợp phổ biến. Thay đổi cấu trúc lớn hơn đối với mã của bạn vẫn có thể yêu cầu nhiều tệp được xây dựng lại.

Thực thi nhanh hơn

Các bản dựng gỡ lỗi tạo ra các tệp nhị phân chạy nhanh hơn đáng kể và các tối ưu hóa mới mang lại hiệu suất xây dựng Phát hành tốt hơn nữa.

Chẩn đoán trình biên dịch tốt hơn

Thông báo lỗi và cảnh báo rõ ràng hơn, cùng với Fix-it mới, giúp viết mã Swift 1.2 phù hợp dễ dàng hơn.

Cải thiện độ ổn định

Các sự cố trình biên dịch phổ biến nhất đã được sửa chữa. Bạn cũng sẽ thấy ít cảnh báo SourceKit hơn trong trình chỉnh sửa Xcode.


0

Đây là một trường hợp khác có thể gây ra sự chậm lại lớn với suy luận kiểu. Điều hành liên kết .

Thay đổi dòng như:

abs(some_optional_variable ?? 0)

đến

abs((some_optional_variable ?? 0) as VARIABLE_TYPE)

đã giúp mang lại thời gian biên dịch của tôi từ 70 đến 13


0

Không có gì hoạt động với tôi trong Xcode 6.3.1 - khi tôi thêm arround 100 tệp Swift Xcode bị treo ngẫu nhiên khi xây dựng và / hoặc lập chỉ mục. Tôi đã thử một tùy chọn mô-đun nhưng không thành công.

Cài đặt và sử dụng Xcode 6.4 Beta thực sự hiệu quả với tôi.


0

Điều này đã hoạt động như ma thuật đối với tôi - Speed ​​Up Swift Compilation . Nó giảm thời gian biên dịch xuống còn 3 phút từ 10 phút.

Nó nói bạn nên bật Whole Module Optimizationtrong khi thêm -Ononevào Other Swift Flags.

Tôi đang sử dụng Swift 3trên Xcode 8.3/Xcode 8.2 .


0

Trộn số nguyên và chữ nổi trong một biểu thức cũng gây ra thời gian biên dịch dài.

1.0 + (1.0 + (1  * (1.0 + 1.0))) // 3429ms

1.0 + (1.0 + (1.0  * (1.0 + 1.0))) // 5ms

Nhiều biểu thức thời gian biên dịch 1000 + ms giảm xuống còn 10 ~ 100ms sau khi tôi đặt một .0số nguyên sau.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.