Làm thế nào tốn kém là phản ánh .NET?


210

Tôi liên tục nghe thấy sự phản ánh xấu như thế nào để sử dụng. Mặc dù tôi thường tránh phản xạ và hiếm khi tìm thấy tình huống không thể giải quyết vấn đề của mình mà không có nó, tôi đã tự hỏi ...

Đối với những người đã sử dụng sự phản chiếu trong các ứng dụng, bạn đã đo các lần truy cập hiệu năng và nó có thực sự tệ đến vậy không?


Bạn cũng có thể muốn kiểm tra câu hỏi này. stackoverflow.com/questions/224232/
Mạnh

1
Sử dụng api tại quickflect.codeplex.com. Nó sẽ tăng tốc độ phản chiếu lên như 500x cho getters / setters / invokers và một số thứ khác. Nguồn và thông tin về cách thức hoạt động cũng có nếu bạn cần mở rộng nó.
Brandon Moore

3
Làm thế nào để thông tin này kiểm tra trong năm 2014? Có gì thay đổi trong 4 năm này không?
Arnthor

1
Nhiệm vụ đơn giản của việc gán một giá trị cho một thuộc tính cá thể chậm hơn khoảng 150 lần khi thực hiện nó với sự phản chiếu (PropertyInfo.SetValue (thể hiện, giá trị)) so với mã hóa đơn giản (instance.property = value) Đây là trong .NET 4.0
Thanocation Ioannidis

Câu trả lời:


130

Nó là. Nhưng điều đó phụ thuộc vào những gì bạn đang cố gắng làm.

Tôi sử dụng sự phản chiếu để tải động các cụm (plugin) và hiệu suất "phạt" của nó không phải là vấn đề, vì hoạt động là điều tôi làm trong quá trình khởi động ứng dụng.

Tuy nhiên, nếu bạn đang phản ánh bên trong một loạt các vòng lặp lồng nhau với các lệnh gọi phản chiếu trên mỗi vòng, tôi sẽ nói bạn nên xem lại mã của mình :)

Đối với các hoạt động "một vài thời gian", sự phản chiếu là hoàn toàn chấp nhận được và bạn sẽ không nhận thấy bất kỳ sự chậm trễ hoặc vấn đề nào với nó. Đây là một cơ chế rất mạnh và nó thậm chí còn được .NET sử dụng, vì vậy tôi không hiểu tại sao bạn không nên thử.


Tôi đã sử dụng sự phản chiếu để có được phương thức, tên lớp của phương thức hiện tại để ghi lại lỗi trong quá trình thử. về cơ bản để tránh mã hóa tên hàm trong khi đăng nhập lỗi. tôi có cần phải lo không?
Sangram Nandkhile

@Sangram không, điều đó tốt
Karthik AMR

@Sangram không, trừ khi bạn có rất nhiều lỗi yêu cầu bắt liên tục, thì đó sẽ là một vấn đề khác :)
Martin Marconcini

5
@Sangram trong khi hiệu suất phản chiếu không phải là vấn đề trong trường hợp của bạn, có vẻ như bạn đang cố gắng thực hiện lại những gì ngoại lệ cũ đơn giản cung cấp một cách thanh lịch hơn nhiều ...
Jacek Gorgoń

152

Trong bài nói chuyện The Performance of Everyday Things , Jeff Richter cho thấy việc gọi một phương thức bằng phản xạ chậm hơn khoảng 1000 lần so với cách gọi thông thường.

Mẹo của Jeff: nếu bạn cần gọi phương thức nhiều lần, hãy sử dụng phản xạ một lần để tìm phương thức đó, sau đó gán cho đại biểu và sau đó gọi đại biểu.


18
Tôi cũng đã tham dự Devscovery và đồng tình với những kết quả này cho .NET 3.5. Biên dịch lại chương trình điểm chuẩn hiệu năng Devscovery cho .NET 4 cho thấy sự cải thiện lớn! Chi phí giảm xuống chậm hơn 100 lần. Sử dụng phản chiếu cho tra cứu typeof () không thay đổi giữa .NET 3.5 và .NET 4.
John Wigger

61

Hiệu suất phản chiếu sẽ phụ thuộc vào việc triển khai (các cuộc gọi lặp đi lặp lại nên được lưu vào bộ đệm, ví dụ: entity.GetType().GetProperty("PropName") :). Vì hầu hết các phản xạ mà tôi thấy trên cơ sở hàng ngày được sử dụng để cư trú các thực thể từ các trình đọc dữ liệu hoặc các cấu trúc kiểu kho lưu trữ khác, tôi đã quyết định đánh giá hiệu năng cụ thể về phản xạ khi nó được sử dụng để lấy hoặc đặt thuộc tính đối tượng.

Tôi đã nghĩ ra một thử nghiệm mà tôi nghĩ là công bằng vì nó lưu trữ tất cả các cuộc gọi lặp lại và chỉ nhân với cuộc gọi SetValue hoặc GetValue thực tế. Tất cả mã nguồn cho bài kiểm tra hiệu suất đều có trong bitbucket tại: https://bitbucket.org/grenade/accessortest . Giám sát được chào đón và khuyến khích.

Kết luận mà tôi đã đưa ra là nó không thực tế và không cung cấp các cải tiến hiệu suất đáng chú ý để loại bỏ sự phản chiếu trong lớp truy cập dữ liệu đang trả về ít hơn 100.000 hàng tại một thời điểm khi việc thực hiện phản chiếu được thực hiện tốt.

Biểu đồ thời gian (y) so với số lượng thực thể (x)

Biểu đồ trên cho thấy đầu ra của điểm chuẩn nhỏ của tôi và cho thấy các cơ chế vượt trội hơn so với phản xạ, chỉ thực hiện đáng chú ý sau khi đánh dấu 100.000 chu kỳ. Hầu hết các DAL chỉ trả về hàng trăm hoặc có thể hàng ngàn hàng tại một thời điểm và ở các mức này, phản xạ chỉ hoạt động tốt.


9
Không cần thiết. Chuyển đổi DAL của bạn chỉ có thể có trên một vài nghìn mặt hàng, nhưng nhân số đó với người dùng đồng thời sử dụng ứng dụng của bạn (nếu là web) và nó có thể tăng lên giống như khi bạn chuyển đổi hàng triệu mặt hàng. Nếu phương pháp cụ thể chậm hơn 100 lần, nó sẽ chậm hơn nhiều trên các tập nhỏ và lớn. Chậm hơn là chậm hơn.
Robert Koritnik

@RobertKoritnik Giả sử rằng các phương thức web trên máy chủ của bạn không đồng bộ
Kurren

@kurren asynchronicity không ảnh hưởng đến sự phản ánh mà là tài nguyên máy chủ. Các phương thức Web không đồng bộ tất nhiên sẽ có thể phục vụ nhiều người dùng hơn, nhưng sự phản chiếu vẫn sẽ chậm. Và phản xạ của chính nó AFAIK dù sao cũng là một quá trình đồng bộ. Mặt khác, dữ liệu tìm nạp sẽ là phần duy nhất sẽ chơi độc đáo với thiết kế không đồng bộ.
Robert Koritnik

3
Phương pháp Hyper trên biểu đồ là gì? Nó khác với Reflector như thế nào?
Truyền thuyết Bryan



12

Kinh nghiệm thích hợp nhất của tôi là viết mã để so sánh bất kỳ hai thực thể dữ liệu cùng loại nào trong một thuộc tính mô hình đối tượng lớn. Rõ ràng là nó đã hoạt động, đã thử nó, chạy như một con chó, rõ ràng.

Tôi đã tuyệt vọng, sau đó qua đêm nhận ra rằng khi thay đổi logic, tôi có thể sử dụng cùng một thuật toán để tự động tạo ra các phương thức để thực hiện so sánh nhưng truy cập tĩnh các thuộc tính. Không mất chút thời gian nào để điều chỉnh mã cho mục đích này và tôi có khả năng so sánh các thực thể sâu sắc với các thực thể với mã tĩnh có thể được cập nhật chỉ với một nút bấm mỗi khi mô hình đối tượng thay đổi.

Quan điểm của tôi: Trong các cuộc trò chuyện với các đồng nghiệp vì tôi đã nhiều lần chỉ ra rằng việc sử dụng phản xạ của họ có thể là tự động mã hóa để biên dịch thay vì thực hiện các hoạt động thời gian chạy và điều này thường đáng xem xét.


Xem xét rằng Visual Studio có hỗ trợ mẫu tuyệt vời như vậy, đó là một cách thiết thực để sử dụng tạo mã
Sebastian

12

Không ồ ạt. Tôi chưa bao giờ gặp vấn đề với nó trong phát triển máy tính để bàn trừ khi, như Martin nói, bạn đang sử dụng nó ở một vị trí ngớ ngẩn. Tôi đã nghe nhiều người có những nỗi sợ hãi vô lý về hiệu suất của nó trong phát triển máy tính để bàn.

Trong Compact Framework (mà tôi thường in), mặc dù nó là khá nhiều lời nguyền rủa và nên tránh như bệnh dịch hạch ở hầu hết các trường hợp. Tôi vẫn có thể thoát khỏi việc sử dụng nó không thường xuyên, nhưng tôi phải thực sự cẩn thận với ứng dụng của nó, điều này ít thú vị hơn. :


5
+1 để dạy tôi một từ mới: anathema. Cũng đề cập đến những nỗi sợ phi lý. Tôi sợ các lập trình viên sợ phi lý - điều đó cho thấy rằng họ không thực sự biết họ đang làm gì và chỉ dựa vào những gì họ làm với những gì người khác nói với họ. ho sùng bái ho
bsneeze

1
Ahhhh Vận chuyển hàng hóa. Bây giờ có một ví dụ tốt về hành vi tò mò của con người.
Quibbledome

10

Nó đủ tệ đến mức bạn phải lo lắng ngay cả về sự phản chiếu được thực hiện bởi các thư viện .NET đối với mã quan trọng về hiệu năng.

Ví dụ sau đây đã lỗi thời - đúng vào thời điểm đó (2008), nhưng từ lâu đã được sửa trong các phiên bản CLR gần đây. Tuy nhiên, sự phản ánh nói chung vẫn là một điều tốn kém!

Case in point: Bạn không bao giờ nên sử dụng một thành viên được khai báo là "Đối tượng" trong câu lệnh khóa (C #) / SyncLock (VB.NET) trong mã hiệu suất cao. Tại sao? Bởi vì CLR không thể khóa loại giá trị, điều đó có nghĩa là nó phải thực hiện kiểm tra loại phản xạ thời gian chạy để xem liệu Đối tượng của bạn có thực sự là loại giá trị thay vì loại tham chiếu hay không.


13
để công bằng, kiểm tra loại phản ánh là nhanh chóng.
Jimmy

1
Đối với 'mã quan trọng về hiệu năng' như vậy, bạn có thực sự nên sử dụng .NET để bắt đầu không?
Seph

1
@Seph: Phần động / phản chiếu của .NET, không. Nhưng thông thường C # /. NET, tại sao không? Tăng tốc C ++ so với C # là cận biên ở lớp ứng dụng (C ++ vẫn nhanh hơn vài% trên các thói quen toán học chuyên sâu). Và tôi đoán bạn không gợi ý lắp ráp ...
DeepSpace101

Một loại giá trị được đóng hộp (ví dụ: đối tượng) có thể bị khóa. @BryceWagner là chính xác.
Fowl

1
Công bằng mà nói (với tôi), chính xác hơn khi nói rằng câu trả lời là "lỗi thời", thay vì "vô nghĩa". Nhận xét của tôi về hành vi của khóa (obj) ĐÃ chính xác tại thời điểm chúng được viết, nhưng hành vi cụ thể thực hiện đó của CLR đã mất từ ​​lâu.
McKenzieG1

5

Như với tất cả mọi thứ trong lập trình, bạn phải cân bằng chi phí hiệu năng với bất kỳ lợi ích nào có được. Reflection là một công cụ vô giá khi được sử dụng cẩn thận. Tôi đã tạo một thư viện ánh xạ O / R trong C #, sử dụng sự phản chiếu để thực hiện các liên kết. Điều này làm việc rất tốt. Hầu hết các mã phản chiếu chỉ được thực hiện một lần, do đó, bất kỳ lần thực hiện nào cũng khá nhỏ, nhưng lợi ích thì rất lớn. Nếu tôi đang viết một thuật toán sắp xếp fandangled mới, tôi có thể sẽ không sử dụng sự phản chiếu, vì nó có thể sẽ mở rộng quy mô kém.

Tôi đánh giá cao rằng tôi đã không trả lời chính xác câu hỏi của bạn ở đây. Quan điểm của tôi là nó không thực sự quan trọng. Sử dụng phản xạ khi thích hợp. Đây chỉ là một tính năng ngôn ngữ khác mà bạn cần tìm hiểu cách thức và thời điểm sử dụng.


3

Sự phản chiếu có thể có tác động đáng chú ý đến hiệu suất nếu bạn sử dụng nó để tạo đối tượng thường xuyên. Tôi đã phát triển ứng dụng dựa trên Khối ứng dụng UI tổng hợp dựa trên sự phản chiếu rất nhiều. Có sự suy giảm hiệu suất đáng chú ý liên quan đến việc tạo đối tượng thông qua sự phản chiếu.

Tuy nhiên trong hầu hết các trường hợp không có vấn đề với việc sử dụng phản xạ. Nếu nhu cầu duy nhất của bạn là kiểm tra một số lắp ráp, tôi muốn giới thiệu Mono.Cecil rất nhẹ và nhanh


3

Sự phản chiếu là tốn kém vì nhiều kiểm tra thời gian chạy phải thực hiện bất cứ khi nào bạn thực hiện một yêu cầu cho một phương thức phù hợp với một danh sách các tham số. Ở đâu đó sâu bên trong, mã tồn tại vòng lặp trên tất cả các phương thức cho một loại, xác minh mức độ hiển thị của nó, kiểm tra loại trả về và cũng kiểm tra loại của từng tham số. Tất cả những thứ này chi phí thời gian.

Khi bạn thực thi phương thức đó bên trong có một số mã thực hiện công việc như kiểm tra bạn đã chuyển một danh sách các tham số tương thích trước khi thực hiện phương thức đích thực tế.

Nếu có thể, luôn luôn khuyến nghị rằng người ta sẽ xử lý phương thức xử lý nếu một người sẽ tiếp tục sử dụng lại nó trong tương lai. Giống như tất cả các mẹo lập trình tốt, thường có ý nghĩa để tránh lặp lại chính mình. Trong trường hợp này, sẽ rất lãng phí nếu liên tục tra cứu phương thức với các tham số nhất định và sau đó thực hiện nó mọi lúc.

Chọc quanh nguồn và xem xét những gì đang được thực hiện.


3

Như với tất cả mọi thứ, đó là tất cả về việc đánh giá tình hình. Trong DotNetNuke, có một thành phần khá cốt lõi được gọi là FillObjectsử dụng sự phản chiếu để đưa vào các đối tượng từ các datarows.

Đây là một kịch bản khá phổ biến và có một bài viết về MSDN, Sử dụng Reflection để ràng buộc các đối tượng kinh doanh để điều khiển biểu mẫu ASP.NET bao gồm các vấn đề về hiệu năng.

Bỏ qua hiệu suất, một điều tôi không thích khi sử dụng sự phản chiếu trong kịch bản cụ thể đó là nó có xu hướng giảm khả năng hiểu mã nhanh chóng, điều này đối với tôi dường như không đáng để bạn nỗ lực khi bạn coi bạn cũng bị mất biên dịch an toàn thời gian trái ngược với các bộ dữ liệu được gõ mạnh hoặc một cái gì đó như LINQ to SQL .


2

Sự phản chiếu không làm giảm đáng kể hiệu suất của ứng dụng của bạn. Bạn có thể thực hiện một số việc nhanh hơn bằng cách không sử dụng sự phản chiếu, nhưng nếu Reflection là cách dễ nhất để đạt được một số chức năng, thì hãy sử dụng nó. Bạn luôn có thể cấu trúc lại mã của mình khỏi Reflection nếu nó trở thành một vấn đề hoàn hảo.


1

Tôi nghĩ rằng bạn sẽ thấy rằng câu trả lời là, nó phụ thuộc. Nó không phải là một vấn đề lớn nếu bạn muốn đưa nó vào ứng dụng danh sách nhiệm vụ của bạn. Đó là một vấn đề lớn nếu bạn muốn đưa nó vào thư viện kiên trì của Facebook.

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.