2012-10-07 17 views
15

Tại sao các phương pháp PropertyInfo để nhận và thiết lập thuộc tính quá chậm? Nếu tôi xây dựng một đại biểu sử dụng Reflection.Emit, nó sẽ nhanh hơn nhiều.Tại sao PropertyInfo SetValue và GetValue quá chậm?

Họ có đang làm điều gì đó quan trọng, để thời gian họ thực hiện có thể được biện minh không? Đó là ... Tôi có thiếu cái gì đó bằng cách sử dụng Reflection.Emit để xây dựng các đại biểu thay vì sử dụng GetValueSetValue của PropertyInfo (ngoài tốc độ phát triển) không?

PS: Vui lòng cung cấp bằng chứng, không chỉ đoán!

+3

FYI, nếu bạn đang tìm kiếm một cách dễ dàng hơn để nhận được một tăng hiệu suất hơn Reflection.Emit, bạn có thể chỉ Delegate.CreateDelegate với PropertyInfo.GetGetMethod/PropertyInfo.GetSetMethod (và bộ nhớ cache đại biểu đương nhiên). – Ani

+0

Tôi phải khóa đối tượng của đối tượng trong ủy nhiệm. Các phương thức 'GetValue' và' SetValue' lấy cá thể đối tượng, tại thời điểm cuộc gọi. –

+0

Delegate.CreateDelegate có thể tạo cả các đối tượng ủy nhiệm mở và đóng. – Ani

Trả lời

16

Việc thực hiện RuntimePropertyInfo (đó là lớp con cụ thể của PropertyInfo với nhiều loại runtime) thực hiện GetValueSetValue bằng cách gọi các phương thức getter và setter thông qua phản ánh (MethodInfo.Invoke), trong khi đại biểu tạo của bạn có thể gọi là phương pháp trực tiếp. Do đó, câu hỏi sẽ tóm tắt: tại sao RuntimeMethodInfo.Invoke quá chậm khi so sánh với lời gọi được biên dịch?

Khi bạn dịch ngược (hoặc nhìn vào các nguồn tài liệu tham khảo cho) RuntimeMethodInfo.Invoke, bạn có thể thấy rằng đây có lẽ là bởi vì Invoke thực hiện rất nhiều nhiệm vụ:

  • nó thực hiện kiểm tra tính nhất quán (làm số lượng và loại các thông số được thông qua khớp với chữ ký không? Ví dụ được thông qua khớp với kiểu khai báo? là một cá thể được truyền mặc dù phương thức là tĩnh?),
  • nó thực hiện khả năng hiển thị và (nếu kiểm tra khả năng hiển thị bị phá vỡ) kiểm tra bảo mật,
  • nó unwraps mảng tham số, xử lý ref pa các ống thông theo cách đặc biệt để chúng có thể được ghi lại sau,
  • nó sẽ mở các tham số nếu cần,
  • cần tìm con trỏ phương thức dựa trên xử lý kiểu thời gian và xử lý phương pháp liên quan đến RuntimeMethodHandle và sau đó gọi phương pháp,
  • nó sẽ trả về giá trị trả lại nếu cần và
  • hộp và đặt vào mảng tham số bất kỳ thông số ref/out nào.

Thời gian chạy sẽ thực hiện kiểm tra tính nhất quán, bảo mật và khả năng hiển thị tương tự khi biên dịch đại biểu của bạn thành mã gốc có thể thực thi. Nó cũng phát ra mã cho boxing/unboxing, vv Tuy nhiên, nó chỉ cần làm những điều này một lần, và sau đó có thể đảm bảo rằng mã này là an toàn để thực thi. Điều này làm cho phương thức thực tế gọi một hoạt động rất rẻ (tải các tham số và chuyển đến địa chỉ phương thức).

Ngược lại, mỗi cuộc gọi đến RuntimeMethodInfo.Invoke (và do đó để GetValue/SetValue) cần phải lặp lại tất cả công việc, vì bối cảnh - thông số, ví dụ, và sử dụng các kiểu trả về - không được biết đến. Và đây có lẽ là lý do tại sao nó quá chậm.

Về những gì bạn có thể bị thiếu: nếu bạn phát ra các đại biểu yêu cầu tài sản của riêng bạn, tất nhiên bạn cần phải giải quyết các thông số về boxing/unboxing, ref/out, v.v.

10

Không cần sử dụng Emit. Nó dễ sử dụng hơn. Bạn có thể tăng tốc độ truy cập như được mô tả trong SO. Lớp trình trợ giúp tạo ra một "con trỏ phương thức" (Hành động/Func) cho trình lấy hoặc thiết lập. Nếu bạn sử dụng lại Action/Func, bạn sẽ có thể thực hiện nhanh như một setter bình thường.

// creating setter (once) 
    var propertyInfo = typeof(T).GetProperty(field); 
    var setter = FastInvoke.BuildUntypedSetter<T>(propertyInfo)); 

    // usage somehow later in a loop of data 
    foreach(var myobject in MySource) 
    { 
    setter(myobject, myValue) 
    } 
+0

http://stackoverflow.com/questions/1027980/improving-performance-reflection-what-alternatives-should-i-consider –

+0

@ sky-dev: Quan điểm của bạn là gì? – Fried

+0

@Fried Liên kết của bạn bị hỏng trong khi liên kết sky-devs hoạt động. Tôi đoán đó là quan điểm của anh ấy. – ViRuSTriNiTy