Những tối ưu hóa nào có thể được thực hiện cho mã thời gian thực mềm trong C #?


8

Tôi đang viết một ứng dụng thời gian thực mềm bằng C #. Một số tác vụ nhất định, như đáp ứng các yêu cầu phần cứng đến từ mạng, cần được hoàn thành trong một lượng mili giây nhất định; tuy nhiên không phải là 100% nhiệm vụ quan trọng để làm như vậy (nghĩa là chúng ta có thể chịu đựng được nó đúng giờ hầu hết thời gian và 1% là không mong muốn nhưng không phải là một thất bại), do đó là phần "mềm".

Bây giờ tôi nhận ra rằng C # là ngôn ngữ được quản lý và ngôn ngữ được quản lý không đặc biệt phù hợp với các ứng dụng thời gian thực. Tuy nhiên, tốc độ chúng ta có thể hoàn thành công việc trong C #, cũng như các tính năng ngôn ngữ, như phản xạ và quản lý bộ nhớ, giúp cho công việc xây dựng ứng dụng này dễ dàng hơn nhiều.

Có bất kỳ tối ưu hóa hoặc chiến lược thiết kế nào người ta có thể thực hiện để giảm số lượng chi phí và tăng tính quyết định? Lý tưởng nhất là tôi sẽ có những mục tiêu sau

  • Trì hoãn việc thu gom rác cho đến khi "an toàn"
  • Cho phép trình thu gom rác hoạt động mà không can thiệp vào các quy trình thời gian thực
  • Ưu tiên luồng / quy trình cho các nhiệm vụ khác nhau

Có cách nào để thực hiện những điều này trong C # không, và có bất kỳ điều gì khác cần chú ý liên quan đến thời gian thực khi sử dụng C # không?

Mục tiêu nền tảng cho ứng dụng là .NET 4.0 Client Profile trên Windows 7 64-bit, với. Tôi đã đặt nó hiện tại thành hồ sơ Khách hàng nhưng đây chỉ là tùy chọn mặc định và không được chọn vì bất kỳ lý do cụ thể nào.


2
Bài viết này có thể giúp bạn ra ngoài. Nó nhắm đến các nhà phát triển trò chơi video, nhưng đó cũng là một ứng dụng thời gian thực mềm. Tuy nhiên, bài viết cũng hơi cũ và trong khi tôi nghi ngờ các nguyên tắc cơ bản đằng sau cách thức hoạt động của GC đã thay đổi nhiều, bạn có thể muốn kiểm tra lại xem nó có còn cập nhật không.
Doval

Bạn đề cập đến C # nhưng không đề cập đến nền tảng đích hoặc thời gian chạy của bạn (ví dụ: .NET trên PC / Unity + Mono / Mono, v.v.) - bạn có thể cho chúng tôi biết thêm một vài chi tiết không?
J Trana

@JTrana Tôi đã chỉnh sửa với nhiều chi tiết hơn
9a3eedi

1) Bạn có thực sự nhận thấy vấn đề? Nhờ vào nền GC, các luồng của bạn chỉ dừng lại trong một thời gian ngắn đối với một số phần nhất định của GC, nhưng nhiều phần khác có thể chạy song song mà không bị nhiễu. 2) Chúng ta đang nói về bao nhiêu phần nghìn giây ở đây?
CodeInChaos

2
@Doval GC của khung nhỏ gọn được sử dụng bởi XNA chạy trên xbox kém hơn nhiều so với GC được sử dụng trong khung thông thường. Có những thay đổi đáng kể đối với GC trong .net 4.0 liên quan đến bộ sưu tập nền sẽ có lợi cho độ trễ. Với bộ sưu tập nền, bộ sưu tập Gen2 đắt tiền có thể chạy trong nền trong khi ứng dụng của bạn tiếp tục hoạt động. Nó thậm chí có thể chạy các bộ sưu tập Gen0 / Gen1 trong khi các bộ sưu tập Gen2 đang được tiến hành.
CodeInChaos

Câu trả lời:


7

Việc tối ưu hóa đáp ứng hai viên đạn đầu tiên của bạn được gọi là Nhóm đối tượng . Nó hoạt động bởi

  1. tạo một nhóm đối tượng khi chương trình bắt đầu,
  2. duy trì các tham chiếu đến các đối tượng đó trong danh sách để chúng không bị thu gom rác,
  3. bàn giao các đối tượng cho chương trình của bạn từ nhóm khi cần thiết và
  4. đưa các đối tượng trở lại hồ bơi khi bạn sử dụng xong.

Bạn có thể tìm thấy một lớp ví dụ thực hiện Nhóm đối tượng bằng cách sử dụng ConcurrentBag tại đây .

Ưu tiên chủ đề / quá trình có thể dễ dàng được thiết lập trong thời gian chạy. Các Chủ đề lớp có phương pháp và tài sản cho phép bạn thiết lập ưu tiên và xử lý mối quan hệ. Các Process Lớp chứa cơ sở vật chất tương tự.


3
Điều này có vẻ như là một cái gì đó nên được thực hiện sau khi ứng dụng hoàn tất và hoạt động, như trong "tối ưu hóa sau". Tuy nhiên, nó có ý nghĩa với tôi như là một phương pháp để tăng tính quyết định.
9a3eedi

1
Có đề xuất nào tôi đưa ra là "tối ưu hóa sớm hơn không?"
Robert Harvey

2
Trình thu gom rác có một vài tùy chọn cấu hình quý giá. Người ta thường cho rằng hành vi của nó là tối ưu cho phần lớn các chương trình. Lưu ý rằng cả Hệ điều hành Windows và .NET Framework đều không được sử dụng trong môi trường thời gian thực cứng. Vâng, tôi biết bạn nói thời gian thực mềm , nhưng vẫn còn.
Robert Harvey

2
@ 9a3eedi: Liên quan đến việc liệu đối tượng có thể được chốt trong khi phát triển ứng dụng đã được thực hiện hay không, tôi có thể đưa ra lời khuyên sau. (1) bạn sẽ phải đưa một nhà máy đối tượng (nhân đôi nhóm đối tượng) vào tất cả các đối tượng mà bạn muốn gộp, (2) thay thế tất cả các phương thức xây dựng bằng các phương thức nhà máy, (3) mỗi đối tượng có một phương thức tái chế quay trở lại nhà máy pool (4) thực hiện các đối tượng của bạn để có thể tái chế: được xóa sạch và sau đó viết lại với thông tin mới. Bạn có thể tính đến điều này nếu bạn cần thiết kế giao diện API trả trước.
rwong

3
Theo kinh nghiệm của tôi, các nhóm đối tượng rất hữu ích cho việc tái chế các mảng lớn (như bộ đệm). Đối với các đối tượng nhỏ, thời gian chạy có xu hướng làm tốt mà không cần gộp thủ công.
CodeInChaos

3

Trì hoãn việc thu gom rác cho đến khi "an toàn"

Bạn có thể làm điều đó, bằng cách đặt chế độ trễ của GC thành LowLatency. Để biết thêm thông tin, xem câu trả lời này trên SO .


Thông minh. Tôi đang tìm kiếm một cái gì đó như thế này. Cảm ơn. Tôi ước tôi có thể đánh dấu hai câu trả lời đúng
9a3eedi

2

Thực hiện cùng một cách tiếp cận mà phát triển trò chơi thực hiện trong môi trường được quản lý và cố gắng giảm thiểu việc tạo / chết đối tượng xuống mức tối thiểu.

vd


sẽ thay đổi một số lớp thành các cấu trúc (bất biến) có giúp tránh việc tạo các đối tượng trung gian ngắn hạn không?
9a3eedi

Sự lựa chọn giữa các cấu trúc và các lớp nói chung không có tác động lớn đến tuổi thọ của "đối tượng" (ngoại trừ các cấu trúc đi kèm với một số logic kiểu "singleton" kiểu giá trị được tích hợp). Trở nên bất biến có thể giúp ích nhưng nó thực sự phụ thuộc vào từng trường hợp.
lzcd

1
@ 9a3eedi: sử dụng các đối tượng bất biến có nghĩa là thực sự bất cứ khi nào bạn phải "biến đổi" một cái gì đó, bạn phải tạo một đối tượng mới với các giá trị được sửa đổi (và có thể vứt bỏ đối tượng cũ để đổi lấy đối tượng mới). Điều đó hoàn toàn ngược lại với những gì bạn muốn, vì nó sẽ để lại rất nhiều bộ nhớ được dọn sạch cho GC phía sau.
Doc Brown

@DocBrown +1. Tuy nhiên, các GC được điều chỉnh cho các đối tượng có thời gian sống ngắn. Bạn không trả tiền cho các đối tượng đã chết khi bộ sưu tập xảy ra (mặc dù việc phân bổ như điên sẽ làm tăng tần suất của các bộ sưu tập). Bạn không sai, nhưng đáng để kiểm tra xem có vấn đề gì ở nơi đầu tiên kể từ khi gộp số tiền vào quản lý bộ nhớ thủ công và đánh bại một nửa mục đích của mã được quản lý (nửa còn lại tránh hành vi không xác định.)
Doval

@DocBrown Ngoài ra, các đối tượng mà trình biên dịch / thời gian chạy có thể chứng minh không thoát khỏi phạm vi của chúng được phân bổ trên ngăn xếp thay vì heap, vì vậy trong một số trường hợp, các đối tượng tạm thời không ảnh hưởng gì đến việc thu gom rác.
Doval

0

Hãy nhớ rằng môi trường đích (Windows) là một O / S đa tác vụ được ưu tiên. Nói cách khác, quá trình thời gian thực mềm mại của bạn chắc chắn sẽ được xử lý trước vào lúc này hay lúc khác, điều này sẽ giới thiệu các độ trễ khác bên cạnh bộ sưu tập rác .NET. Bạn có thể giảm thiểu nó bằng cách giảm giá trị lát cắt thời gian (lượng tử) (mặc định là khoảng 16ms) và nâng mức độ ưu tiên của quy trình của bạn (nhưng có giới hạn thực tế), nhưng vẫn còn tồn tại trước khi các quy trình thiết yếu khác vẫn cần để làm công cụ. Tất cả điều này không liên quan gì đến ngôn ngữ lập trình; nó là nền tảng cho O / S.

Đặt vấn đề sang một bên, ứng dụng của bạn chạy trên một máy Windows vượt trội có thể sẽ có thể cung cấp độ trễ trong vài mili giây MOST OF TIME. Nó chắc chắn không thể được đảm bảo 100% thời gian, hoặc bất cứ điều gì gần gũi. Ngay cả khi điều chỉnh (lượng tử ngắn, mức độ ưu tiên cao), thỉnh thoảng bạn vẫn sẽ nhận được độ trễ cao. Đó là bản chất của con thú.

Điểm mấu chốt: nếu bạn cần thời gian phản hồi được đảm bảo, đặc biệt là theo thứ tự vài mili giây, Windows có lẽ không phải là lựa chọn tốt nhất cho O / S phân phối.


Tôi đồng ý. Tôi sẵn sàng chấp nhận một vài phần nghìn giây chậm trễ ở đây và đó, do đó là phần "thời gian thực mềm", nhưng lý tưởng nhất là tôi muốn giảm thiểu càng nhiều càng tốt. Có lẽ xuống dòng tôi có thể chuyển ứng dụng sang Linux (với Mono) và có lẽ điều đó sẽ cho phép tôi tinh chỉnh những thứ này
9a3eedi
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.