Hàng trăm ngàn người, mỗi Go FAQ: Why goroutines instead of threads?:
Đó là thực tế để tạo ra hàng trăm ngàn goroutines trong không gian địa chỉ tương tự.
Bài kiểm tra test/chan/goroutines.go tạo 10.000 và có thể dễ dàng làm nhiều hơn, nhưng được thiết kế để chạy nhanh; bạn có thể thay đổi số trên hệ thống của mình để thử nghiệm. Bạn có thể dễ dàng chạy hàng triệu, cho đủ bộ nhớ, chẳng hạn như trên máy chủ.
Để hiểu số lượng tối đa của goroutines, lưu ý rằng chi phí cho mỗi goroutine chủ yếu là ngăn xếp. Mỗi câu hỏi thường gặp một lần nữa:
… goroutines, có thể rất rẻ: chúng có ít chi phí vượt quá bộ nhớ cho ngăn xếp, chỉ là vài kilobyte.
Một back-of-the-phong bì tính toán là giả định rằng mỗi goroutine có một 4 KiB page phân bổ cho chồng (4 KiB là khá kích thước thống nhất), cộng với một số chi phí nhỏ cho một khối điều khiển (như a Thread Control Block) cho thời gian chạy; điều này đồng ý với những gì bạn đã quan sát (trong năm 2011, trước khi đi 1.0). Vì vậy, 100 Ki thói quen sẽ mất khoảng 400 MiB bộ nhớ, và 1 Mi thói quen sẽ mất khoảng 4 GiB bộ nhớ, mà vẫn có thể quản lý trên máy tính để bàn, một chút cho một chiếc điện thoại, và rất dễ quản lý trên một máy chủ. Trong thực tế, ngăn xếp bắt đầu đã thay đổi kích thước từ một nửa trang (2 KiB) đến hai trang (8 KiB), do đó, điều này là chính xác.
Kích thước ngăn xếp bắt đầu đã thay đổi theo thời gian; nó bắt đầu ở 4 KiB (một trang), sau đó trong 1,2 đã được tăng lên 8 KiB (2 trang), sau đó trong 1,4 đã giảm xuống còn 2 KiB (nửa trang). Những thay đổi này là do các ngăn xếp phân đoạn gây ra các vấn đề về hiệu suất khi chuyển đổi nhanh chóng giữa các phân đoạn ("chia ngăn nóng"), do đó tăng lên để giảm thiểu (1,2), sau đó giảm khi ngăn xếp phân đoạn được thay thế bằng ngăn xếp liền kề (1.4):
Go 1.2 Ghi chú Phát hành: Stack size:
trong Go 1.2, kích thước tối thiểu của ngăn xếp khi một goroutine được tạo ra đã được nâng lên từ 4KB để 8KB
Go 1,4 Ghi chú Phát hành: Changes to the runtime:
kích thước khởi động mặc định cho ngăn xếp của goroutine trong 1,4 đã được giảm từ 8192 byte xuống 2048 byte.
Bộ nhớ Per-goroutine chủ yếu là ngăn xếp, và nó bắt đầu thấp và phát triển để bạn có thể có nhiều goroutines rẻ. Bạn có thể sử dụng một ngăn xếp bắt đầu nhỏ hơn, nhưng sau đó nó sẽ phải phát triển sớm hơn (đạt được không gian với chi phí thời gian), và lợi ích giảm do khối điều khiển không co lại. Có thể loại bỏ ngăn xếp, ít nhất là khi được hoán đổi (ví dụ, thực hiện tất cả phân bổ trên heap, hoặc lưu ngăn xếp để đống trên chuyển đổi ngữ cảnh), mặc dù điều này làm tổn thương hiệu suất và làm tăng thêm độ phức tạp. Điều này là có thể (như trong Erlang), và có nghĩa là bạn chỉ cần khối điều khiển và ngữ cảnh đã lưu, cho phép một hệ số 5 × –10 × khác trong số các goroutine, bị giới hạn bởi kích thước khối điều khiển và kích thước trên goroutine biến địa phương. Tuy nhiên, điều này không hữu ích, trừ khi bạn cần hàng triệu con goroutines ngủ nhỏ.
Vì việc sử dụng chính có nhiều goroutin cho các nhiệm vụ liên quan đến IO (cụ thể là xử lý chặn các hệ thống, đặc biệt là mạng hoặc hệ thống tệp IO), bạn có nhiều khả năng chạy vào giới hạn OS trên các tài nguyên khác. ổ cắm hoặc tay cầm tập tin: golang-nuts › The max number of goroutines and file descriptors?. Cách thông thường để giải quyết vấn đề này là với pool của tài nguyên khan hiếm, hoặc đơn giản hơn là chỉ giới hạn số lượng thông qua số semaphore; xem Conserving File Descriptors in Go và Limiting Concurrency in Go.
Chuyển đổi của bạn từ ~ 4k/mỗi goroutine (điều này đã thay đổi từ bản phát hành sang bản phát hành; và bạn cũng cần phải tính đến việc sử dụng chồng goroutine) vào một maxium dựa trên bộ nhớ được cài đặt là thiếu sót. Tối đa sẽ dựa trên bộ nhớ ảo nhỏ hơn (thường là 2-3GB cho hệ điều hành 32 bit), hoặc bộ nhớ vật lý * cộng * không gian hoán đổi có sẵn, hoặc giới hạn tài nguyên bộ nhớ của quá trình (thường là không giới hạn). Ví dụ. trên một máy 64bit với thiết lập swap sane bộ nhớ vật lý được cài đặt là không thích hợp với bất kỳ * giới hạn * (nhưng hiệu suất sẽ giảm khi trao đổi bắt đầu xảy ra). –
Tôi nghĩ rằng điều này có chứa một điều kiện chủng tộc, vì không có đồng bộ hóa rõ ràng để đảm bảo tất cả các goroutines đã bắt đầu trước khi bộ đếm được so sánh với 'n'. Bạn may mắn mỗi lần? :) –
sân chơi go báo cáo '2758,41 byte' trên mỗi goroutine, chạy đi 1.5.1. –