2010-03-15 22 views
15

Tôi đang phát triển trò chơi sử dụng XNA và C# và cố gắng tránh gọi new struct() nhập mã mỗi khung hình như tôi nghĩ rằng nó sẽ làm hỏng GC. "Nhưng chờ đã," tôi tự nhủ, "struct là một loại giá trị. GC không nên gọi như vậy, phải không?" Vâng, đó là lý do tại sao tôi hỏi ở đây.Điều gì xảy ra khi các loại giá trị được tạo?

Tôi chỉ có một ý tưởng rất mơ hồ về những gì xảy ra với các loại giá trị. Nếu tôi tạo một cấu trúc mới trong một cuộc gọi hàm, cấu trúc có được tạo trên ngăn xếp không? Nó sẽ chỉ đơn giản được đẩy và popped và hiệu suất không có một hit? Hơn nữa, sẽ có một số giới hạn bộ nhớ hoặc hiệu suất hoạt động nếu, nói rằng, tôi cần phải tạo ra nhiều trường hợp trong một cuộc gọi duy nhất?

Lấy ví dụ, mã này:

spriteBatch.Draw(tex, new Rectangle(x, y, width, height), Color.White); 

Rectangle trong trường hợp này là một struct. Điều gì xảy ra khi Hình chữ nhật mới đó được tạo? Các hàm ý của việc phải lặp lại dòng đó nhiều lần như thế nào (nói, hàng ngàn lần)? Hình chữ nhật này có được tạo ra, một bản sao được gửi đến phương thức Draw, và sau đó bị loại bỏ (nghĩa là không có bộ nhớ nào được ăn nhiều hơn Draw được gọi theo cách đó trong cùng một chức năng)?

P.S. Tôi biết điều này có thể là tối ưu hóa trước khi trưởng thành, nhưng tôi hầu như tò mò và muốn hiểu rõ hơn về những gì đang xảy ra.

Trả lời

4

Khi cấu trúc mới được tạo, nội dung của nó được đặt thẳng vào vị trí bạn chỉ định - nếu đó là biến phương thức, nó sẽ nằm trên ngăn xếp; nếu nó được gán cho một biến lớp, nó đi vào bên trong cá thể lớp được trỏ tới (trên heap).

Khi biến cấu trúc được sao chép (hoặc trong trường hợp của bạn, được chuyển đến hàm), các byte tạo cấu trúc đều được sao chép vào đúng vị trí trên ngăn xếp hoặc bên trong lớp (nếu bạn đang đặt trường hoặc thuộc tính trên một thể hiện của một kiểu tham chiếu).

Mặc dù có thể sao chép các byte, trình biên dịch JIT có khả năng sẽ tối ưu hóa tất cả các bản sao không cần thiết để nó thực hiện càng nhanh càng tốt. Nói chung, nó không phải cái gì bạn cần phải lo lắng về - điều này là rất nhiều tối ưu hóa vi mô :)

Điều này có trả lời câu hỏi của bạn không?

+0

Nếu tôi gọi cùng một chức năng hơn và hơn, là một hình chữ nhật mới đẩy mỗi cuộc gọi đến Vẽ, và xuất hiện khi Draw trả về? – Bob

+0

Có, nhưng lưu ý rằng đẩy và popping stack khung chỉ là incrementing/decrementing một con trỏ (một hướng dẫn máy đơn). Và trình biên dịch JIT sẽ tối ưu hóa mọi thứ cho vương quốc. – thecoop

+0

@Bob: Vâng, mặc dù tôi đoán nó có thể - theo lý thuyết - rằng JIT * có thể * nhìn thấy các cuộc gọi giống hệt nhau và bộ nhớ cache giá trị để gửi nhiều lần, nhưng điều này dường như rất khó đưa ra các chẩn đoán có liên quan đến việc phát hiện điều này và có thể dễ dàng bị loại trừ. –

1

Trong khi các loại giá trị đi trên ngăn xếp, vẫn có tác động đến phân bổ và xử lý tất cả bộ nhớ đó mỗi khung - đặc biệt trên Xbox 360. Trên máy tính, bạn có thể sẽ không nhận thấy sự khác biệt, nhưng trên 360 bạn có lẽ sẽ.

+0

Không phải tất cả các loại giá trị đi trên stack. Nếu c của loại khách hàng có một loại giá trị int tuổi, sau đó giá trị của nó vẫn đi trên heap. – JonH

+0

Thật sao? Nó sẽ là tốt hơn để tạo ra một hình chữ nhật mới ở đầu khung và tái sử dụng đó? – Bob

+0

Đặt cược tốt nhất là thử chạy hàng triệu lần cả hai cách và xem cái nào nhanh hơn. Bạn cũng có thể so sánh IL được tạo cho cả hai phương thức. – thecoop

1

Các loại giá trị được tạo trên ngăn xếp nếu được khai báo cục bộ hoặc trên vùng heap nếu một phần của cá thể đối tượng (như là một phần của cá thể đối tượng). Trong mọi trường hợp, các thể hiện cấu trúc không được GC thu thập, chúng sẽ bị phá hủy khi vùng chứa của chúng nằm ngoài phạm vi.

Bài viết MSDN struct (C#) có thêm một số thông tin về điều này.

1

Đây chỉ là để thêm vào câu trả lời của vòng lặp. Đối với các kiểu tham chiếu toán tử new phân bổ một cá thể mới của kiểu trên heap và gọi hàm tạo đã chỉ định.

Đối với cấu trúc, toán tử new khởi tạo các trường theo hàm tạo đã chỉ định. Tuy nhiên, có thể khởi tạo một cấu trúc mà không cần sử dụng new. Trong trường hợp đó, tất cả các trường trong cấu trúc đều chưa được khởi tạo và không thể được sử dụng cho đến khi chúng được khởi tạo một cách rõ ràng.

Để biết thêm thông tin, xem the description on MSDN.

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