19

Hãy nói rằng tôi có một vòng lặp mà trả về một loạt các đối tượng NSData autoreleased ...Trong ARC, bạn vẫn có thể tạo @autoreleasepool cho vòng lặp?

NSData* bigData = ... 
while(some condition) { 
    NSData* smallData = [bigData subdataWithRange:...]; 
    //process smallData 
} 

Theo ARC, tôi nên vẫn quấn một @autoreleasepool xung quanh tình trạng while?

NSData* bigData = ... 
@autoreleasepool { 
    while(some condition) { 
     NSData* smallData = [bigData subdataWithRange:...]; 
     //process smallData 
    } 
} 

Lý do tại sao tôi hỏi là tôi nhìn thấy số lượng phân bổ sinh hoạt trong các văn bản đi qua mái nhà cho các đối tượng NSData của tôi mà gọi một phương pháp dataWith... như trái ngược với một phương pháp initWith.... Khi tôi sử dụng initWith..., số lượng phân bổ sống là nhiều, ít hơn nhiều.

Tốt hơn bạn nên chọn phương thức initWith... bất cứ khi nào có thể?

Trả lời

13

Có, bạn vẫn nên sử dụng các bể tự động trả lời khi sử dụng các phương pháp tiện lợi trong vòng lặp chặt chẽ. Tất cả các quy tắc quản lý bộ nhớ cũ vẫn được áp dụng theo ARC, trình biên dịch chỉ đơn thuần là tiêm các RR cho bạn. Kiểm tra bài đăng tuyệt vời của Mike Ash tuyệt vời!

Link

+0

Cảm ơn bạn đã liên kết tuyệt vời! –

+10

Mỗi câu trả lời của @ Chuck: @autoreleasepool cần phải đi * bên trong * vòng lặp để nó hoạt động tốt. Thành ngữ là 'while (x) @autoreleasepool {...}', không phải '@autoreleasepool {while (x) {...}}'. – Quuxplusone

+0

Điều này là đơn giản và không chính xác. ARC thường có thể tối ưu hóa việc sử dụng nhóm autorelease cho các phương thức trả về một đối tượng +0 (hầu hết là sử dụng 'autorelease'). –

7

Theo ARC, tôi nên vẫn quấn một @autoreleasepool xung quanh điều kiện thời gian?

Có. Autorelease Pools vẫn còn tại chỗ, và phát triển và bật như trước. Trình biên dịch chỉ thêm vào và kết hợp các hoạt động cần thiết giữ lại và giải phóng khi ARC được kích hoạt (lặp lại Logan), dựa trên các phương thức được hiển thị cho TU và các quy ước đặt tên mặc định.

Thực hiện trong ARC gần giống với tính năng tham khảo thủ công: Ngăn xếp nhóm tự động phát hiện vẫn tồn tại. Một sự khác biệt là trình biên dịch có thể đặt các hoạt động đếm tham chiếu hơi khác so với cách bạn viết nó (không theo cách không chính xác) và có thể bỏ qua các chu kỳ giữ lại không cần thiết.

Tốt hơn bạn nên chọn phương thức initWith ... bất cứ khi nào có thể?

WRT giảm thiểu tối đa tăng trưởng heap so với các đối tác được tự động phát hành: Có. Đó luôn là trường hợp. Nó đặc biệt quan trọng trên các thiết bị iOS, nơi bộ nhớ khá hạn chế.

Ngoại lệ cho điều này là khi đối tượng có thể tránh phân bổ. Ví dụ:

NSString * copy = [NSString stringWithString:arg]; 

trong trường hợp này, copy có thể là [[arg retain] autorelease]. Lưu ý rằng trong trường hợp này, copy vẫn được tự động phát hành, nhưng bạn thường không nên đi đến độ dài lớn để kiểm tra sự hiện diện của các tối ưu hóa như vậy. Lưu ý: Bạn cũng nên sử dụng copy = [arg copy] ... [arg release] tại đây.

Tiền thưởng khác là số dư mất cân bằng ref thường được ghi lại trước đó khi đối tượng không bao giờ được tự động phát hành và gần với trang gọi (thay vì khi Autorelease Pool cuối cùng xuất hiện).

Hiệu suất với các bể tự động lớn thực sự tồi tệ hơn nhiều so với hầu hết mọi người sẽ giả sử. Nếu bạn có thể tránh tùy thuộc vào chúng (ví dụ: sử dụng alloc + init ...+ release), bạn có thể làm cho chương trình của bạn đáng chú ý nhanh hơn. Tạo hồ bơi autorelease rõ ràng là rẻ, và có thể giúp giảm thiểu vấn đề này. Khi phân bổ lớn và/hoặc nhiều, tránh sử dụng autorelease trên chúng nếu có thể, và quấn các phần này trong các bể tự động phát hiện rõ ràng.

13

Tôi nghĩ rằng vấn đề của bạn là hồ bơi autorelease được cho là phải đi bên trong vòng lặp. Với vòng lặp bên trong khối autorelease thay vì ngược lại, các đối tượng tích lũy sẽ không được giải phóng cho đến khi kết thúc vòng lặp.

+0

Tôi đã không nghĩ đến việc đặt '@ autoreleasepool' bên trong vòng lặp ... nhờ mẹo. –

Các vấn đề liên quan