8

Mã sau sẽ chiếm ~ 410MB bộ nhớ và sẽ không phát hành lại. (Phiên bản sử dụng dispatch_sync thay vì dispatch_async sẽ yêu cầu bộ nhớ ~ 8MB)
Tôi mong đợi mức sử dụng bộ nhớ cao nhưng sẽ giảm xuống một lần nữa ... Trường hợp bị rò rỉ ở đâu?GCD dispatch_async leak memory?

int main(int argc, const char * argv[]) { 
    @autoreleasepool { 
    for (int i = 0; i < 100000; i++) { 
     dispatch_async(dispatch_get_global_queue(QOS_CLASS_UTILITY, 0), ^{ 
     NSLog(@"test"); 
     }); 
    } 
    NSLog(@"Waiting."); 
    [[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:60]]; 
    } 
    return 0; 
} 

tôi đã cố gắng:

  • Thêm @autoreleasepool xung quanh và bên trong vòng lặp
  • Thêm NSRunLoop run vòng lặp

Tôi đã thử nhiều kết hợp và không bao giờ nhìn thấy một giảm bộ nhớ (ngay cả sau khi chờ đợi phút). Tôi nhận thức được hướng dẫn tham khảo GCD, trong đó có tuyên bố sau:

Mặc dù GCD hàng đợi công văn có hồ bơi autorelease riêng của họ, họ không đảm bảo như khi những hồ đang cạn kiệt.

Có rò rỉ bộ nhớ trong mã này không? Nếu không, có cách nào để thực thi hàng đợi để giải phóng/thoát các khối đã hoàn thành không?

Trả lời

1

Khối Objective-C là cấu trúc C, tôi nghĩ bạn tạo 100000 đối tượng khối để thực thi chúng trong chuỗi nền và chúng đợi trong khi hệ thống có thể chạy chúng. Thiết bị của bạn có thể thực thi số lượng chuỗi giới hạn, điều đó có nghĩa là nhiều khối sẽ đợi trước khi hệ điều hành khởi động chúng.

Nếu bạn thay đổi "không đồng bộ" thành "đồng bộ", một đối tượng khối tiếp theo sẽ được tạo sau khi khối trước đó sẽ được hoàn tất và hủy.

UPD

Về GCD hồ bơi.

GCD thực hiện các tác vụ trên nhóm luồng GCD, các luồng được tạo bởi hệ thống và được quản lý bởi hệ thống. Hệ thống lưu trữ các luồng để tiết kiệm thời gian CPU, mọi nhiệm vụ điều phối đều thực thi trên chuỗi miễn phí.

Từ tài liệu:

-

Blocks nộp cho hàng đợi công văn được thực hiện trên một vũng đề quản lý hoàn toàn bởi hệ thống. Không có đảm bảo nào được thực hiện đối với luồng mà tác vụ thực thi.

-

Nếu bạn chạy các nhiệm vụ theo nhiệm vụ đồng bộ, sau đó tồn tại các chủ đề miễn phí (từ GCD bơi thread) để thực hiện công việc tiếp theo, sau khi đã hoàn thành (vì chủ đề chính nhiệm vụ hiện tại đang chờ đợi trong khi nhiệm vụ thực thi, và không thêm nhiệm vụ mới vào hàng đợi), và hệ thống không cấp phát NSThread mới (Trên mac của tôi, tôi đã thấy 2 luồng). Nếu bạn chạy các nhiệm vụ như async, thì hệ thống có thể phân bổ nhiều NSThreads (để đạt được hiệu suất tối đa, trên mac của tôi nó gần 67 chủ đề), bởi vì hàng đợi toàn cầu chứa nhiều tác vụ.

Here bạn có thể đọc về số lượng tối đa của nhóm chủ đề GCD.

Tôi đã thấy trong tiểu sử Alocations rằng có nhiều NSThread được phân bổ và không bị hủy. Tôi nghĩ rằng đó là hệ thống hồ bơi, sẽ được giải phóng nếu cần thiết.

+0

Đó là sự thật nhưng không phải là câu trả lời cho câu hỏi. Việc sử dụng bộ nhớ sẽ giảm xuống một lần nữa (ít nhất) sau khi tất cả các khối đã kết thúc. Nhưng đó không phải là trường hợp ở đây. Sự tăng đột biến sử dụng bộ nhớ cao sẽ hoàn toàn ổn. – Andreas

+0

Tôi đã chỉnh sửa câu trả lời của mình. –

0

Luôn đặt @autoreleasepool bên trong mọi cuộc gọi GCD và bạn sẽ không gặp vấn đề gì. Tôi đã có cùng một vấn đề và đây là giải pháp duy nhất.

int main(int argc, const char * argv[]) { 
    @autoreleasepool { 
    for (int i = 0; i < 100000; i++) { 
     dispatch_async(dispatch_get_global_queue(QOS_CLASS_UTILITY, 0), ^{ 
     // everything INSIDE in an @autoreleasepool 
     @autoreleasepool { 
      NSLog(@"test"); 
     } 
     }); 
    } 
    NSLog(@"Waiting."); 
    [[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:60]]; 
    } 
    return 0; 
}