Làm thế nào Swift có thể nhanh hơn nhiều so với Objective-C trong những so sánh này?


115

Apple ra mắt ngôn ngữ lập trình mới Swift tại WWDC14 . Trong bài trình bày, họ đã thực hiện một số so sánh hiệu suất giữa Objective-C và Python. Sau đây là hình ảnh về một trong các slide của họ, so sánh ba ngôn ngữ thực hiện một số loại đối tượng phức tạp:

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

Thậm chí còn có một biểu đồ đáng kinh ngạc hơn về so sánh hiệu suất bằng thuật toán mã hóa RC4 .

Rõ ràng đây là một cuộc nói chuyện tiếp thị và họ đã không đi sâu vào chi tiết về cách thức này được thực hiện trong mỗi. Tôi để tôi tự hỏi mặc dù:

  1. Làm thế nào một ngôn ngữ lập trình mới có thể nhanh hơn rất nhiều?
  2. Là các kết quả Objective-C gây ra bởi một trình biên dịch tồi hoặc có một cái gì đó kém hiệu quả hơn trong Objective-C so với Swift?
  3. Làm thế nào bạn sẽ giải thích tăng hiệu suất 40%? Tôi hiểu rằng việc thu gom rác / kiểm soát tham chiếu tự động có thể tạo ra một số chi phí bổ sung, nhưng điều này nhiều không?

13
@MathewFoscarini Obj-C đi đến trình biên dịch chương trình, nhưng nó có một cơ chế gửi tin nhắn đối tượng đắt tiền. Đối với hầu hết các công việc GUI không quan trọng, nhưng để sắp xếp nó rất quan trọng.
Donal Fellows

17
Sự so sánh với Python là công cụ tìm đầu thực sự ở đây.
asthasr

9
@syrion tiếp thị và ngôn ngữ dường như mượn từ cú pháp của python (giống như golang). Họ đang cố gắng nói "này, các nhà phát triển python, bạn có thể viết một cái gì đó không quá xa lạ trên mac và nó nhanh hơn rất nhiều, thậm chí nhanh hơn cả Objective C mà bạn chưa bao giờ thực sự hiểu được"

4
@MichaelT Tôi hiểu điều đó, nhưng nó vẫn kỳ quặc. Bất cứ ai biết bất cứ điều gì về ngôn ngữ đều sẽ nhận ra rằng Python, như một ngôn ngữ được giải thích, đơn giản là sẽ không ở trong cùng một sân bóng như Objective-C hoặc các ngôn ngữ được biên dịch khác (đối với hầu hết các tác vụ). Sử dụng nó như là một điểm chuẩn là kỳ lạ.
asthasr

7
Chúng có lẽ có nghĩa là thời gian cần thiết để viết mã ...
Lukas Eder

Câu trả lời:


62

Đầu tiên, (IMO) so sánh với Python gần như vô nghĩa. Chỉ so sánh với Objective-C là có ý nghĩa.

  • Làm thế nào một ngôn ngữ lập trình mới có thể nhanh hơn rất nhiều?

Mục tiêu-C là một ngôn ngữ chậm. (Chỉ có phần C là nhanh, nhưng đó là vì C) Nó chưa bao giờ cực kỳ nhanh. Nó chỉ đủ nhanh cho mục đích (của Apple) và nhanh hơn các phiên bản cũ hơn của họ. Và nó chậm vì ...

  • Do Objective-C có kết quả từ một trình biên dịch tồi hay có một cái gì đó kém hiệu quả hơn trong Objective-C so với Swift?

Mục tiêu-C đảm bảo mọi phương thức được gửi động. Không có công văn tĩnh nào cả. Điều đó khiến không thể tối ưu hóa chương trình Objective-C hơn nữa. Chà, có lẽ công nghệ JIT có thể là một số trợ giúp, nhưng AFAIK, Apple thực sự ghét đặc điểm hiệu suất không thể đoán trước và tuổi thọ đối tượng. Tôi không nghĩ rằng họ đã áp dụng bất kỳ công cụ JIT nào. Swift không có đảm bảo công văn động như vậy trừ khi bạn đặt một số thuộc tính đặc biệt để tương thích Objective-C.

  • Làm thế nào bạn sẽ giải thích tăng hiệu suất 40%? Tôi hiểu rằng việc thu gom rác / kiểm soát tham chiếu tự động có thể tạo ra một số chi phí bổ sung, nhưng điều này nhiều không?

GC hoặc RC không quan trọng ở đây. Swift cũng đang sử dụng RC là chủ yếu. Không có GC ở đó, và cũng sẽ không trừ khi có một bước nhảy lớn về kiến ​​trúc trên công nghệ GC. (IMO, nó là mãi mãi) Tôi tin rằng Swift có nhiều chỗ hơn để tối ưu hóa tĩnh. Đặc biệt là các thuật toán mã hóa ở mức độ thấp, vì chúng thường dựa vào các phép tính số lượng lớn và đây là một chiến thắng lớn cho các ngôn ngữ gửi tĩnh.

Thật ra tôi rất ngạc nhiên vì 40% dường như quá nhỏ. Tôi mong đợi nhiều hơn nữa. Dù sao, đây là bản phát hành ban đầu và tôi nghĩ tối ưu hóa không phải là mối quan tâm chính. Swift thậm chí không đầy đủ tính năng! Họ sẽ làm cho nó tốt hơn.

Cập nhật

Một số người tiếp tục làm phiền tôi để tranh luận rằng công nghệ GC là vượt trội. Mặc dù những điều dưới đây có thể tranh cãi, và chỉ là ý kiến ​​rất thiên vị của tôi, nhưng tôi nghĩ rằng tôi phải nói để tránh tranh luận không cần thiết này.

Tôi biết các GC bảo thủ / theo dõi / thế hệ / gia tăng / song song / thời gian thực là gì và chúng khác nhau như thế nào. Tôi nghĩ rằng hầu hết các độc giả cũng đã biết điều đó. Tôi cũng đồng ý rằng GC rất tốt trong một số lĩnh vực và cũng cho thấy thông lượng cao trong một số trường hợp.

Dù sao, tôi nghi ngờ tuyên bố về thông lượng của GC luôn tốt hơn RC. Hầu hết chi phí hoạt động của RC đến từ hoạt động đếm số lần khóa và khóa để bảo vệ biến số đếm số lần đếm. Và thực hiện RC thường cung cấp một cách để tránh các hoạt động đếm. Trong Objective-C, có __unsafe_unretainedvà trong Swift, (mặc dù nó vẫn không rõ ràng đối với tôi) unowned. Nếu chi phí vận hành đếm lại không được chấp nhận, bạn có thể thử từ chối chúng một cách có chọn lọc bằng cách sử dụng các cơ chế. Về mặt lý thuyết, chúng ta có thể mô phỏng kịch bản sở hữu gần như duy nhất bằng cách sử dụng các tham chiếu không giữ lại rất mạnh mẽ để tránh chi phí RC. Ngoài ra tôi hy vọng trình biên dịch có thể tự động loại bỏ một số hoạt động RC không cần thiết rõ ràng.

Không giống như hệ thống RC, AFAIK, từ chối một phần các loại tham chiếu không phải là một tùy chọn trên hệ thống GC.

Tôi biết có nhiều đồ họa và trò chơi được phát hành đang sử dụng hệ thống dựa trên GC và cũng biết hầu hết trong số chúng đang phải chịu đựng vì thiếu tính quyết đoán. Không chỉ cho đặc tính hiệu suất, mà còn đối tượng quản lý trọn đời. Unity chủ yếu được viết bằng C ++, nhưng phần C # nhỏ bé gây ra tất cả các vấn đề hiệu suất kỳ lạ. Các ứng dụng lai HTML và vẫn bị ảnh hưởng bởi các đột biến không thể đoán trước trên bất kỳ hệ thống nào. Được sử dụng rộng rãi không có nghĩa là vượt trội. Nó chỉ có nghĩa là dễ dàng và phổ biến đối với những người không có nhiều lựa chọn.

Cập nhật 2

Một lần nữa để tránh tranh luận hoặc thảo luận không cần thiết, tôi thêm một số chi tiết.

@Asik cung cấp một ý kiến ​​thú vị về gai nhọn của GC. Đó là cách chúng ta có thể coi cách tiếp cận ở mọi nơi kiểu giá trị như một cách để từ chối công cụ GC. Điều này khá hấp dẫn và thậm chí có thể thực hiện được trên một số hệ thống (ví dụ phương pháp hoàn toàn chức năng). Tôi đồng ý rằng điều này là tốt đẹp trong lý thuyết. Nhưng trong thực tế nó có một số vấn đề. Vấn đề lớn nhất là ứng dụng một phần của thủ thuật này không cung cấp các đặc điểm không có đột biến thực sự.

Bởi vì vấn đề độ trễ luôn là tất cả hoặc không có vấn đề . Nếu bạn có một khung hình tăng đột biến trong 10 giây (= 600 khung hình), thì toàn bộ hệ thống rõ ràng là không thành công. Đây không phải là về cách tốt hơn hoặc tồi tệ hơn. Nó chỉ là vượt qua hoặc thất bại. (hoặc ít hơn 0,0001%) Vậy nguồn gốc của GC tăng đột biến ở đâu? Đó là sự phân phối tải trọng kém. Và đó là vì GC về cơ bản là không xác định. Nếu bạn tạo bất kỳ rác nào, thì nó sẽ kích hoạt GC và tăng đột biến sẽ xảy ra. Tất nhiên, trong thế giới lý tưởng nơi tải GC sẽ luôn lý tưởng, điều này sẽ không xảy ra, nhưng tôi đang sống trong thế giới thực chứ không phải thế giới lý tưởng tưởng tượng.

Sau đó, nếu bạn muốn tránh tăng đột biến, bạn phải loại bỏ tất cả các loại ref khỏi toàn bộ hệ thống. Nhưng nó khó, điên rồ và thậm chí là không thể do phần không thể điều khiển được như hệ thống và thư viện lõi .NET. Chỉ cần sử dụng hệ thống không phải là dễ dàng hơn nhiều .

Không giống như GC, RC về cơ bản mang tính quyết định và bạn không phải sử dụng tối ưu hóa điên rồ này (chỉ hoàn toàn là loại giá trị) chỉ để tránh tăng đột biến. Những gì bạn phải làm là theo dõi và tối ưu hóa phần gây ra đột biến. Trong các hệ thống RC, spike là vấn đề thuật toán cục bộ, nhưng trong các hệ thống GC, gai luôn là vấn đề hệ thống toàn cầu.

Tôi nghĩ rằng câu trả lời của tôi đã đi quá nhiều chủ đề, và chủ yếu chỉ là sự lặp lại của các cuộc thảo luận hiện có. Nếu bạn thực sự muốn yêu cầu một số ưu thế / kém hơn / thay thế hoặc bất cứ điều gì khác về nội dung của GC / RC, có rất nhiều cuộc thảo luận hiện có trong trang web này và StackOverflow, và bạn có thể tiếp tục chiến đấu ở đó.


4
Thu gom rác, đặc biệt là thế hệ, thường nhanh hơn đáng kể so với đếm tham chiếu.
Jan Hudec

9
@JanHudec Nhanh hơn đáng kể của bạn chỉ đơn giản là vô nghĩa trong lĩnh vực đồ họa thời gian thực. Đó là lý do tại sao tôi đề cập đến bước nhảy vọt lớn là cần thiết trên GC. GC thế hệ thậm chí không gần như không tăng đột biến cả về lý thuyết và thực tế.
Eonil

5
Nhanh hơntăng đột biến là các thể loại hoàn toàn trực giao. Thu gom rác thế hệ nhanh hơn . Họ không tăng đột biến.
Jan Hudec

4
Những gì bạn đang nói là thông lượng . Nhanh hơn luôn luôn là một thuật ngữ mơ hồ, và có thể có nghĩa là bất cứ điều gì bởi bối cảnh. Nếu bạn muốn tranh luận về ý nghĩa của các thuật ngữ, bạn nên sử dụng thuật ngữ chính xác hơn thay vì nhanh hơn đặc biệt là xem xét bối cảnh hiện tại - đồ họa thời gian thực.
Eonil

11
@JanHudec: Trên các thiết bị di động hoặc bất kỳ thiết bị nào có tài nguyên bị hạn chế, GC không nhanh hơn đáng kể và trên thực tế là một phần chính của vấn đề.
Mason Wheeler

72

Nhanh hơn 3,9 lần so với python, ngôn ngữ luôn mất hầu hết các điểm chuẩn bởi biên độ đáng kể (ok, nó ngang bằng với Perl, Ruby và PHP; nhưng nó thua bất cứ thứ gì được gõ tĩnh), không phải là điều ai cũng nên tự hào.

Các trò chơi tiêu chuẩn cho thấy C ++ chương trình mà hơn theo độ nhanh hơn so với các chương trình python trong hầu hết các trường hợp. Sẽ không tốt hơn nhiều khi so sánh với Java, C # (trên Mono), OCaml, Haskell và thậm chí Clojure, không được gõ tĩnh.

Vì vậy, câu hỏi thực sự là làm thế nào mà Objective-C chỉ nhanh hơn 2,8 lần so với python. Rõ ràng họ đã cẩn thận chọn điểm chuẩn trong đó công văn chậm hoàn toàn của ObjC làm tổn thương rất nhiều. Bất kỳ ngôn ngữ gõ tĩnh nào cũng có thể làm tốt hơn. Trong sắp xếp đối tượng phức tạp, có nhiều phương thức gọi để so sánh các đối tượng và so sánh thực tế có lẽ không phức tạp lắm. Vì vậy, nếu Swift tận dụng ít nhất một số lợi thế của thông tin loại, nó có thể dễ dàng thực hiện tốt hơn các cuộc gọi phương thức và không có đủ các hoạt động khác mà ObjC có thể tốt hơn.

Tất nhiên, như trò chơi điểm chuẩn thể hiện rõ ràng, hiệu suất tương đối trong các nhiệm vụ khác nhau rất khác nhau, do đó, một điểm chuẩn không thực sự đại diện. Nếu họ có điểm chuẩn nơi nó có lợi thế lớn hơn, họ sẽ cho chúng ta thấy rằng một thay vào đó, vì vậy đối với các nhiệm vụ khác, nó có thể không tốt hơn hoặc không nhiều.


13
Tôi không hiểu lắm về câu trả lời này. Bạn đang trả lời "làm thế nào là nhanh hơn" bằng cách nói "điểm chuẩn là thiếu sót"? Đó có phải là điểm bạn đang làm? Tôi không thấy câu trả lời của những gì đang được hỏi.
Bryan Oakley

15
@BryanOakley: Tôi không nghĩ rằng điểm chuẩn là thiếu sót, nhưng khả năng họ đã chọn một điểm chuẩn trong đó Swift nhanh hơn chắc chắn phải được xem xét.
Jan Hudec

23
Có thể câu trả lời cho "Làm thế nào là Swift nhanh hơn?" có thể là "Thật ra không phải vậy", @BryanOakley; đó là ý chính mà tôi nhận được từ câu trả lời của Jan. "Nói dối, dối trá chết tiệt, và thống kê", sau khi tất cả.
Josh Caswell

4
Cách đây một thời gian, chúng tôi đã điểm chuẩn Codename One chạy trên iOS và việc triển khai Java của chúng tôi nhanh hơn nhiều so với Objective-C codenameone.com/blog/, Jan Jan là chính xác, công văn động rất chậm, nếu họ cải thiện chúng dù chỉ một chút thì một số điểm chuẩn sẽ cho thấy một sự cải thiện rất lớn Nếu họ cải thiện ARC thậm chí bằng một phân số (nhờ phân tích mã tốt hơn), họ có thể thoát khỏi một số lượng phức tạp vô lý. Ngôn ngữ càng bị hạn chế thì trình biên dịch càng có thể làm để tối ưu hóa (xem Java) và Swift thêm các hạn chế.
Shai Almog

7
Câu trả lời của Jan là một câu trả lời hoàn hảo cho Q1 và có thể là Q2. Khi tôi xem điểm chuẩn của một sự kiện tiếp thị là bài phát biểu, tôi nghĩ: "Wow, chỉ có 1,3 lần trong trường hợp tốt nhất được chọn. Chúng ta sẽ có kết quả trung bình là bao nhiêu? 0,3 lần?"
Amin Negm-Awad

5

Objective-C tự động gửi mọi cuộc gọi phương thức.

Giả thuyết: Điểm chuẩn sử dụng kiểu gõ tĩnh để cho trình biên dịch Swift nâng comparephương thức tra cứu ra khỏi sortvòng lặp. Điều này đòi hỏi một hạn chế kiểu hẹp chỉ cho phép các đối tượng phức tạp trong mảng, không phải các lớp con của Complex.

(Trong Objective-C, bạn có thể nâng công cụ tra cứu phương thức theo cách thủ công nếu bạn thực sự muốn, bằng cách gọi hỗ trợ thời gian chạy ngôn ngữ để tra cứu con trỏ phương thức. Tốt hơn là bạn nên chắc chắn rằng tất cả các cá thể trong mảng đều thuộc cùng một lớp .)

Giả thuyết: Swift tối ưu hóa các cuộc gọi đếm tham chiếu ra khỏi vòng lặp.

Giả thuyết: Điểm chuẩn Swift sử dụng cấu trúc phức thay cho đối tượng Objective-C, do đó, so sánh sắp xếp không cần gửi phương thức động (vì nó không thể được phân lớp) hoặc công việc đếm tham chiếu (vì đó là loại giá trị).

(Trong Objective-C, bạn có thể quay lại C / C ++ để thực hiện miễn là nó không liên quan đến các đối tượng Objective-C, ví dụ: sắp xếp một mảng C của các cấu trúc.)


3

Thành thật mà nói, trừ khi họ phát hành nguồn cho các thử nghiệm mà họ đang sử dụng, tôi sẽ không tin bất cứ điều gì Apple nói về chủ đề này. Hãy nhớ rằng, đây là công ty đã chuyển từ PPC sang Intel dựa trên những lo ngại về sức mạnh khi 6 tháng trước họ nói rằng Intel đã hút và thực sự hành hạ chú thỏ Intel trong một quảng cáo. Tôi muốn thấy bằng chứng khó có thể bác bỏ rằng Swift nhanh hơn ObjC trong nhiều danh mục hơn là chỉ sắp xếp.

Ngoài ra, bạn phải đặt câu hỏi về bất kỳ số liệu thống kê nào được phát hành tại WWDC vì chúng có mùi tiếp thị trên tất cả chúng.

Tất cả những gì được nói tôi đã không thực hiện bất kỳ thử nghiệm nào giữa swift và ObjC, nhưng từ những gì tôi biết thì swift có các phần mở rộng LLVM IR của riêng nó và có thể là việc tối ưu hóa được thực hiện nhiều hơn vào thời gian biên dịch so với ObjC.

Tiết lộ đầy đủ: Tôi đang viết một trình biên dịch Swift mã nguồn mở được đặt tại https://ind.ie/phoenix/

Nếu bất cứ ai muốn giúp đảm bảo rằng Swift không chỉ có sẵn trên phần cứng của Apple, hãy cho tôi biết và tôi rất vui khi có bạn.


2
cái này đọc giống như một bình luận thô lỗ, xem Cách trả lời
gnat

2
Bây giờ có tốt hơn không? :)
greg.casamento

0

Tôi đã đấu tranh bản thân mình thông qua hướng dẫn Swift và dường như Swift thấy mình thực tế hơn (khiến tôi nghĩ về Visual Basic) với ít 'đối tượng' hơn so với Objective-C. Nếu họ đã tính đến C hoặc C ++, tôi cho rằng cái sau sẽ thắng, vì chúng thậm chí còn nhiều thời gian biên dịch hơn.

Trong trường hợp này, tôi cho rằng Objective-C là nạn nhân của sự thuần khiết hướng đối tượng (và chi phí).


13
Thực hiện một tiêu chuẩn "sắp xếp đối tượng phức tạp" sẽ hơi khó khăn trong một ngôn ngữ như C không có triển khai đối tượng gốc. Cho rằng khán giả của buổi nói chuyện này có khả năng là các lập trình viên Objective-C 100%, so với một ngôn ngữ như C ++ cũng không có nhiều ý nghĩa. Quan điểm của swift không phải là "này, đây là ngôn ngữ tuyệt vời nhất!" nhưng đúng hơn là "này, nó nhanh hơn ngôn ngữ bạn đang sử dụng để phát triển OSX / iOS".
Bryan Oakley

10
C có một mức hoàn hảo tốt qsortsẽ cho phép sắp xếp đối tượng phức tạp; nó chỉ sử dụng một cuộc gọi lại để hiểu các đối tượng trong tầm tay. Tôi nghi ngờ C ++ bị mất vì std::sortsẽ làm xấu hổ Swift. (Vì là mẫu, trình biên dịch C ++ có thể tối ưu hóa nó rất nhiều, cho đến khi không kiểm soát vòng lặp.)
MSalters

@MSalters: Tôi hoàn toàn đồng ý với bạn. Cả C và C ++ đều có khả năng vượt qua Swift. Nó sẽ có thể có được thử nghiệm thực hiện. Tôi sẵn sàng thực hiện cùng một chuẩn với Swift, Objective-C, C ++ và C.
Painted Black

@BryanOakley cũng vậy, "Ngôn ngữ này yêu cầu dấu ngoặc vuông ít hơn!"
Nick Bedford

1
Câu trả lời này hoàn toàn không giữ nước và gây hiểu lầm khủng khiếp. OO không thực sự chậm, trên thực tế, các hệ thống nhanh nhất bạn tìm thấy sẽ là C ++, Java và C # và phong cách (rất nhiều OO hoặc không) lập trình sẽ có rất ít liên quan đến tốc độ kết quả trừ khi bạn thực sự có mã xấu.
Bill K
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.