Odbicie: czy używanie odbicia jest nadal „złe” czy „wolne”? Co zmieniło się w wyniku refleksji od 2002 roku?

21

Zauważyłem, kiedy mam do czynienia z Wyrażeniami lub Drzewami wyrażeń, często używam odbicia, aby ustawić i uzyskać wartości we właściwościach i co masz. Przyszło mi do głowy, że użycie refleksji wydaje się być coraz powszechniejsze. Rzeczy takie jak DataAnotations do walidacji, Atrybuty ciężkich ORM itp. Zastanawiam się: co zmieniło się od lat, które upłynęły wiele lat temu, kiedy kazano mi unikać refleksji, jeśli to w ogóle możliwe?

Co więc, jeśli coś się zmieniło? Czy to tylko prędkość maszyn? Czy wprowadzono zmiany w ramach, aby przyspieszyć refleksję?

Czy nic się tak naprawdę nie zmieniło? Czy używanie odbicia jest nadal „złe” czy „wolne”?

blesh
źródło
2
Refleksja zawsze będzie wolniejsza niż bezpośrednie połączenia, ponieważ musisz wykonać kilka kroków, aby znaleźć i sprawdzić, czy to, co dzwonisz, istnieje.
Michael K,
Zawsze było źle ... Oczywiście, czasami nie masz wyboru, to od programisty zależy, kiedy to będzie, i unikaj tego inaczej.
Ramhound
Wykonanie Odbicia za pomocą gettype w celu wyciągnięcia jednego elementu w wyliczeniu jest wciąż ponad 30 razy szybsze niż zgłoszenie wyjątku za pomocą Enum.Parse (). Tak więc odbicie czasami wygrywa.
Brain2000

Odpowiedzi:

16

Odbicie nie jest ani złe, ani powolne. To po prostu narzędzie. Jak wszystkie narzędzia, jest bardzo cenny w niektórych scenariuszach, a nie tak cenny dla innych.

Jeśli wydajność jest naprawdę problemem, zawsze możesz użyć biblioteki takiej jak FasterFlect .

Dalsza lektura
Jeśli odbicie jest nieefektywne, kiedy jest najbardziej odpowiednie?

Robert Harvey
źródło
Lub dynamic- najwyraźniej o rząd wielkości szybszy niż odbicie.
Oded
1
Wydajność wcale nie jest problemem. Po prostu żywo pamiętam ludzi, którzy unikali refleksji w 2002 roku, jakby to była plaga. Zastanawiam się, co się zmieniło od tego czasu.
blesh
3
@ Rozwiązywanie problemów: Nic. Ludzie są teraz bardziej zaznajomieni z tym i mniej się go boją.
Robert Harvey
5
Mogę być wszystkim „wysiąść mój trawnik” tu i powiedzieć, że Lisp miał to na długo przed OOP istniał ...
Michael K
Słusznie. Zastanawiałem się tylko, czy to różnica prędkości maszyn w ciągu ostatnich dziesięciu lat zrobiła różnicę, czy rzeczywiście nastąpiły zmiany w systemie. Odbicie to poprawiło wydajność.
blesh
17

Powodem, dla którego ludzie obawiają się niepotrzebnego korzystania z odbicia, nie jest wydajność: tak, korzystanie z odbicia wiąże się z pewnym nakładem pracy, ale często rozwiązanie problemu bez niego wymaga innego podejścia o porównywalnej złożoności, a nawet jeśli nie, koszty ogólne są rzadko znaczące (szczególnie dla rozwoju na poziomie aplikacji).

Korzystając z refleksji, niektóre ważne założenia dotyczące kodu źródłowego, które normalnie można przyjąć, są łamane, a narzędzia takie jak „Znajdź wszystkie referencje” przestają działać niezawodnie. Refleksja zasadniczo usuwa również większość typów bezpieczeństwa, jakie wymusza kompilator, powiedzmy w C #, a większość błędów programistycznych, które system typów wychwytuje i tłumaczy na błędy kompilatora, teraz stają się w najlepszym razie błędami czasu wykonywania lub w najgorszym razie bardzo niejasnymi błędami.

Dlaczego więc ludzie używają refleksji? Mówiąc wprost, ponieważ pomimo opisanych wyżej problemów jest to bardzo cenne narzędzie. Po zastanowieniu, niektóre zalety programowania dynamicznego można uzyskać w statycznym, ściśle typowym języku, takim jak C #, a dynamiczne języki programowania niedawno pokazały swoje zalety, szczególnie w dziedzinie programowania internetowego - PHP, JavaScript i dość wyraźnie Python , wszystkie używają dynamicznego pisania i okazały się dobre do programowania w sieci. Ale ponieważ językiem wciąż jest C #, możesz zdecydować się na zachowanie większości aplikacji w ściśle typowym idiomie OOP i napisać małą część, w której dynamiczne zachowanie naprawdę robi różnicę dzięki refleksji.

Typowym przykładem jest konieczność ujawnienia metod jako wywołań usługi internetowej (przy użyciu protokołu jeszcze nie wbudowanego w .NET). Podejście OOP ściśle wpisane działa, ale jest zbyt restrykcyjne i niezdarne. Ale jeśli użyjesz refleksji do odwzorowania wywołań metod i par klucz / wartość na argumenty, możesz raz napisać hydraulikę takiej usługi sieci, a następnie użyć jej w dowolnej klasie, którą lubisz.

tdammers
źródło
13

Odbicie jest nadal znacznie wolniejsze niż bezpośrednie połączenia. Zmieniły się dwie rzeczy:

  • Środowiska wykonawcze mają zoptymalizowane mechanizmy odbicia, dzięki czemu różnica się zmniejszyła
  • Procesory stały się szybsze, więc łatwiej można tolerować małe nieefektywności

Razem te dwa czynniki obniżyły koszt refleksji do punktu, w którym możesz rutynowo z niego korzystać (w stosownych przypadkach z POV w zakresie konserwacji) i czekać, aż profiler powie ci, czy to rzeczywiście wąskie gardło (i być całkiem pewnym, że większość czas to nie będzie).

Michael Borgwardt
źródło
4
Niestety, procesory stały się wolniejsze - zazwyczaj na urządzeniach mobilnych i na serwerze, na którym ludzie próbują wycisnąć jak najwięcej wydajności ze swoich serwerów ze względu na koszty ich uruchomienia.
gbjbaanb
@gbjbaanb: Dam ci urządzenia mobilne, ale na serwerze zakup większego sprzętu niż optymalizacja kodu jest w większości przypadków akceptowanym i racjonalnym wyborem, ponieważ koszty zakupu i uruchomienia serwerów są znacznie niższe niż koszty optymalizacji kodu.
Michael Borgwardt,
2
W niektórych sytuacjach koszty serwera znacznie przewyższają koszty programowania. W dużym skalowanym stylu. Mimo że serwery są wzmocnione, wydajność może być nawet bardziej krytyczna niż na komputerze klienckim. Jest to indywidualny scenariusz.
Lord Tydus,
1
@ Lord Tydus: jasne, ale opisany przypadek to rzadki wyjątek.
Michael Borgwardt,