Cú pháp và ngữ nghĩa đã được xác định rõ bởi các câu trả lời xuất sắc khác cho câu hỏi này. Bởi vì thực thi và hiệu suất không chi tiết tốt, tôi sẽ thêm câu trả lời của tôi.
Sự khác biệt chức năng giữa 3 là gì?
Tôi luôn coi nguyên tử là một mặc định khá tò mò. Ở cấp độ trừu tượng mà chúng tôi làm việc, sử dụng các thuộc tính nguyên tử cho một lớp làm phương tiện để đạt được 100% an toàn luồng là một trường hợp góc. Đối với các chương trình đa luồng thực sự chính xác, sự can thiệp của lập trình viên gần như chắc chắn là một yêu cầu. Trong khi đó, đặc điểm hiệu suất và thực hiện vẫn chưa được chi tiết chuyên sâu. Đã viết một số chương trình đa luồng rất nhiều trong những năm qua, tôi đã tuyên bố nonatomic
toàn bộ tài sản của mình vì nguyên tử không hợp lý cho bất kỳ mục đích nào. Trong quá trình thảo luận về các chi tiết về tính chất nguyên tử và phi nguyên tử của câu hỏi này , tôi đã thực hiện một số hồ sơ gặp phải một số kết quả gây tò mò.
Chấp hành
Đồng ý. Điều đầu tiên tôi muốn làm rõ là việc thực hiện khóa được xác định và trừu tượng hóa việc thực hiện. Louis sử dụng @synchronized(self)
trong ví dụ của mình - tôi đã xem đây là một nguồn gây nhầm lẫn phổ biến. Việc thực hiện không thực sự sử dụng @synchronized(self)
; nó sử dụng khóa spin cấp đối tượng . Minh họa của Louis là tốt cho một minh họa cấp cao bằng cách sử dụng các cấu trúc mà chúng ta đều quen thuộc, nhưng điều quan trọng là phải biết nó không sử dụng @synchronized(self)
.
Một sự khác biệt nữa là các thuộc tính nguyên tử sẽ giữ lại / giải phóng chu kỳ các đối tượng của bạn trong getter.
Hiệu suất
Đây là phần thú vị: Hiệu suất sử dụng truy cập thuộc tính nguyên tử trong các trường hợp không kiểm chứng (ví dụ: đơn luồng) có thể thực sự rất nhanh trong một số trường hợp. Trong các trường hợp ít hơn lý tưởng, việc sử dụng truy cập nguyên tử có thể tốn hơn 20 lần chi phí nonatomic
. Trong khi trường hợp Contested sử dụng 7 luồng thì chậm hơn 44 lần đối với cấu trúc ba byte ( Core i7 Quad Core 2.2 GHz , x86_64). Cấu trúc ba byte là một ví dụ về thuộc tính rất chậm.
Lưu ý bên lề thú vị: Các bộ truy cập do người dùng định nghĩa của cấu trúc ba byte nhanh hơn 52 lần so với các bộ truy cập nguyên tử tổng hợp; hoặc 84% tốc độ của các phụ kiện không phải là tổng hợp.
Đối tượng trong các trường hợp tranh cãi cũng có thể vượt quá 50 lần.
Do số lượng tối ưu hóa và các biến thể trong việc triển khai, khá khó để đo lường các tác động trong thế giới thực trong các bối cảnh này. Bạn có thể thường nghe một cái gì đó như "Tin tưởng nó, trừ khi bạn hồ sơ và thấy nó là một vấn đề". Do mức độ trừu tượng, thực sự khá khó để đo lường tác động thực tế. Lượm lặt chi phí thực tế từ hồ sơ có thể rất tốn thời gian, và do trừu tượng, khá không chính xác. Đồng thời, ARC vs MRC có thể tạo ra sự khác biệt lớn.
Vì vậy, hãy lùi lại, không tập trung vào việc thực hiện truy cập tài sản, chúng tôi sẽ bao gồm các nghi phạm thông thường như objc_msgSend
, và kiểm tra một số kết quả cấp cao trong thế giới thực cho nhiều cuộc gọi đến người nhận NSString
trong các trường hợp không kiểm chứng (giá trị tính bằng giây):
- MRC | nonatomic | thủ công getters: 2
- MRC | nonatomic | tổng hợp getter: 7
- MRC | nguyên tử | tổng hợp getter: 47
- ARC | nonatomic | getter tổng hợp: 38 (lưu ý: ARC's thêm số đếm ref ở đây)
- ARC | nguyên tử | tổng hợp getter: 47
Như bạn có thể đoán, hoạt động đếm / đạp xe tham chiếu là một đóng góp đáng kể với nguyên tử và theo ARC. Bạn cũng sẽ thấy sự khác biệt lớn hơn trong các trường hợp tranh cãi.
Mặc dù tôi rất chú ý đến hiệu suất, tôi vẫn nói ngữ nghĩa đầu tiên! . Trong khi đó, hiệu suất là ưu tiên thấp cho nhiều dự án. Tuy nhiên, biết chi tiết thực hiện và chi phí của các công nghệ bạn sử dụng chắc chắn không gây hại. Bạn nên sử dụng công nghệ phù hợp với nhu cầu, mục đích và khả năng của mình. Hy vọng rằng điều này sẽ giúp bạn tiết kiệm một vài giờ so sánh, và giúp bạn đưa ra quyết định sáng suốt hơn khi thiết kế chương trình của mình.