2013-02-13 11 views
8

Dostarczam skróty dla zestawów danych, aby odcisnąć palcem dane i zidentyfikować je za pomocą skrótu - jest to kluczowy przypadek użycia szybkich skrótów takich jak SHA1 i MD5.O ile szybsza jest natywna implementacja natywnych skrótów kryptograficznych w systemie Windows niż wersja zarządzana .Net?

W .Net istnieje opcja przejścia z natywnymi lub zarządzanymi implementacjami niektórych z tych skrótów (w każdym razie warianty SHA). Szukam implementacji zarządzanej przez MD5 i nie wydaje się, aby była ona w .Net Framework, ale zastanawiałem się, czy owinięta natywna CSP jest i tak szybsza, i czy powinienem po prostu użyć jej treści, że nie będzie perfekcji problemy z korzystaniem z niego. Górna odpowiedź na Why is there no managed MD5 implementation in the .NET framework? wskazuje, że szybsza wydajność może być przyczyną braku zarządzanego wariantu.

Czy to prawda, a jeśli tak, to o ile szybciej jest natywny CSP?

+0

Wdrożenie MS MD5 bani, przynajmniej na krótkich łańcuchach. Zoptymalizowałem ~ 10 razy p/wywołując OpenSSL. – CodesInChaos

+0

Miło mi to słyszeć, ponieważ byłem zainteresowany testowaniem implementacji OpenSSL. – codekaizen

+0

Mała reklama: Jeśli chcesz odporny na kolizję (ani MD5, ani SHA-1), to szybka funkcja hash do identyfikacji plików, możesz rozważyć Blake2. Został zaprojektowany dla tego scenariusza. Ale potrzebujesz natywnej biblioteki dla maksymalnej wydajności. – CodesInChaos

Odpowiedz

17

Niestety, owinięta natywna CSP dla MD5 - MD5CryptoServiceProvider - jest znacznie wolniejsza niż czysto zarządzana implementacja. Jest to uparty punkt widzenia, który utrzymuje, że natywny kod jest jednoznacznie szybszy niż kod zarządzany: w wielu przypadkach jest odwrotnie. To jest taki przypadek, przynajmniej w pomiarze "głowa-głowa".

Korzystając z translated reference MD5 implementation by David Anson, skonstruowałem model quick performance test (source), który ma na celu pomiar dużych różnic w wydajności między dwiema implementacjami. Podczas gdy dla małych macierzy danych różnica jest znikoma, zgodnie z oczekiwaniami, przy około 16kB natywna implementacja zaczyna wykazywać potencjalnie znaczne opóźnienie - rzędu milisekund. To może nie wydawać się dużo, ale jest to rząd wielkości wolniejszy niż czysto zarządzana implementacja. Różnica ta jest utrzymywana w miarę wzrostu wielkości mieszanych danych, a przy największej badanej tablicy danych - ~ 250 MB - różnica czasu procesora wynosiła około 8,5 sekundy. Biorąc pod uwagę, że taki skrót jest często używany do pobierania bardzo dużych plików odcisków palców, to dodatkowe opóźnienie staje się zauważalne, nawet w stosunku do często znacznie większych opóźnień z operacji we/wy.

Nie jest jasne, skąd pochodzi opóźnienie, ponieważ nie wykonano czystego natywnego testu (takiego, który zrezygnowałby z zawijania CSP i zużycia w zarządzanym kodzie), ale biorąc pod uwagę prawie identyczny kształt wykresów na według skali logu wydaje się, że implementacje zarządzane i natywne mają tę samą wewnętrzną wydajność, ale wydajność natywnego kodu jest "przesunięta" w dół w wydajności prawdopodobnie ze względu na koszt współdziałania kodu natywnego i zarządzanego w czasie wykonywania. To jest performance difference between wrapped native CSPs and pure managed implementations has also been reproduced and documented by other investigators.

Oprócz odpowiedzi na pytanie "o ile szybsza jest natywna implementacja" w tym konkretnym przypadku, mam nadzieję, że ten dowód będzie służył prompt more reflection and investigation, gdy pojawi się pytanie rodzimego kontra zarządzanego, łamiąc długotrwałą i szkodliwą reakcję na podobne pytania, że ​​natywny kod jest zawsze szybszy, a więc w jakiś sposób lepszy. Kod zarządzany jest wyraźnie bardzo szybki, nawet w tej wrażliwej na wydajność domenie mieszania danych zbiorczych.

MD5 Hash Computation Time MD5 Hash Computation Time (Logarithmic)

+0

'" przesunięty "w dół' ale w przestrzeni logarytmicznej, która odpowiada stałej różnicy prędkości czynnika. Jest to prawdopodobnie niska implementacja natywna.Jeśli zrobione poprawnie, natywna powinna pokonać zarządzane mierzalne na dużych danych. – usr

+1

Tak, właśnie o to mi chodziło: "wydaje się, że zarządzane i natywne implementacje mają taką samą wewnętrzną wydajność". Ale dlaczego natywny kod miałby większą wydajność? Jeśli przeanalizujesz, co powoduje jitter i unikniesz przerw w kolekcji GC, uzyskasz mniej więcej taką samą wydajność, chyba że specjalnie wybierzesz instrukcje sprzętowe/rejestry, których jitter CLR nie ma. Kod zarządzany nie jest wolniejszy z powodów magicznych, istnieją pewne rzeczy, które spowalniają go, czego można uniknąć w przypadku wrażliwego kodu. – codekaizen

+1

Cóż, nie zgadzam się z tym, że zarządzane i rodzime mają ten sam wewnętrzny perf i dane są na to dowodem. Dane są dowodem * przeciwko * PInvoke narzutów przy dużych rozmiarach danych, ponieważ częstotliwość wywołań PInvoke powinna zbliżać się do zera. Usługa .NET JIT jest ogólnie bardzo słaba. Dobry kompilator języka C może go przewyższyć. Zbadałem szczegółowo gen zarządzanego kodu i rozczarowało go pod wieloma względami. Jako praktyczny przykład zarządzany JIT dopiero niedawno uzyskał wsparcie dla instrukcji rotacyjnych (nie jest to jeszcze wydane). – usr

Powiązane problemy