Szybki kod
FastCode to projekt programistyczny typu open source , którego celem jest zapewnienie ulepszonych procedur bibliotecznych środowiska wykonawczego dla Embarcadero Delphi i C++ Builder . Odkąd został uruchomiony w 2003 roku przez Dennisa Kjaera Christensena, wniósł wysoce zoptymalizowaną funkcjonalność do 32-bitowej biblioteki wykonawczej Delphi (RTL). FastCode jest wyjątkowy wśród wkładów do komercyjnych bibliotek wykonawczych kompilatorów ze względu na swój charakter oparty na społeczności i otwartym kodzie źródłowym.
Struktura
Projekt zorganizowany jest w formie konkursu podzielonego na wyzwania. Każde wyzwanie przyjmuje jedną funkcję i optymalizuje ją pod kątem wielu celów. Projekt zapewnia narzędzia do analizy porównawczej i sprawdzania poprawności wkładu każdej funkcji. Za wkład przyznawany jest jeden punkt (punkty przyznawane są maksymalnie jednej funkcji za cel), a zwycięzcy celu przyznawane jest dziesięć punktów. Utrzymywana jest lista wszystkich autorów i ich wyników, a pod koniec każdego roku, aż do 2008 r., obchodzono zwycięzcę. Borland , Codegear i Embarcadero , właściciele Delphi i C++ Builder , historycznie sponsorowali nagrody.
Większość uczestników konkursu to twórcy asemblera, którzy często wykorzystują 32-bitowy kod specyficzny dla procesora i dodatkowe zestawy instrukcji, takie jak MMX , SSE , SSE2 , SSE3 , SSSE3 i SSE4 .
Projekt cieszy się wsparciem Embarcadero, który docenia wkład zespołu FastCode i włącza ich kod do bazy kodów dla Delphi. Domyślny menedżer pamięci dla Embarcadero Delphi , FastMM4, jest zwycięzcą wyzwania FastCode Memory Manager.
Projekt był po raz pierwszy hostowany na stronie OptimalCode Roberta Lee, a strona główna kodu źródłowego to [1] , ostatnio zaktualizowana w 2008 r. Kod źródłowy zawiera zarówno ulepszone procedury, jak i zestawy testów do testów porównawczych procedur. W 2017 r. procedury porównawcze dla funkcji Move, FillChar i menedżera pamięci zostały przeniesione do wersji 64-bitowej i są dostępne pod adresem [2] .
Testowanie
Projekt FastCode wkłada wiele wysiłku w testowanie i koncentruje się na dostarczaniu oprogramowania o bardzo wysokiej jakości. Testowanie dzieli się na dwie kategorie - testowanie poprawności i testowanie szybkości.
Walidacja
Walidacja jest przeprowadzana na wszystkich procesorach z zestawu docelowego i bardzo często na innych procesorach i systemach operacyjnych ( Windows XP , Windows Vista , Windows 7 itp.). Walidacja jest przeprowadzana dla wielu różnych danych wejściowych funkcji, zarówno w przypadku normalnego użycia, jak i przypadków użycia błędów. Walidacja jest przeprowadzana na podstawie znanych poprawnych wartości i implementacji referencyjnych, takich jak istniejące funkcje RTL.
Analiza porównawcza
Test porównawczy jest wykonywany na wszystkich procesorach, które są częścią bieżącego celu ustawionego w danym momencie. Te procesory były lub są częścią zestawów docelowych: ( Intel Pentium 3 , Intel Pentium M , Intel Pentium 4 , Intel Core , Intel Core 2 , AMD Athlon XP , AMD Opteron , AMD Phenom ). Dołożono wszelkich starań, aby testy porównawcze były stabilne i realistyczne. Szczególnie test porównawczy wyzwania menedżera pamięci był trudny do uzyskania rzetelności, a dzienniki użycia menedżera pamięci zostały utworzone na podstawie normalnego użytkowania rzeczywistych aplikacji, a następnie odtworzone przez test porównawczy.
Cele
Testy przeprowadzone na całym zestawie docelowym. Nowy zestaw celów jest ustalany co roku na podstawie ankiety, w której społeczność FastCode może głosować. Zestaw docelowy zazwyczaj składa się z sześciu procesorów, z których cztery pochodzą od Intela, a dwa od AMD. Wskaźnik ten został wybrany w celu naśladowania udziałów w rynku. Oprócz tych sześciu docelowych procesorów istnieje dziesięć celów zdefiniowanych jako połączenie sześciu procesorów. Te dziesięć celów nazywa się celami obliczonymi i może to być tylko prędkość lub kombinacja prędkości i rozmiaru. Maksymalny dozwolony zestaw instrukcji jest inny dla każdego celu. Celem może być „kara za rozmiar IA32” lub „SSE2”. Kara za rozmiar jest ustalana dla każdego wyzwania w drodze ankiety.
Lista wyzwań
W ramach projektu FastCode podjęto następujące wyzwania [3] :
- AES ( zaawansowany standard szyfrowania )
- AnsiStringReplace (Zastępuje wystąpienia podłańcucha w ciągu).
- ArcCos (oblicza odwrotny cosinus. Przeciążone wersje dla precyzji pojedynczej, podwójnej i rozszerzonej).
- ArcSin (Oblicza odwrotny sinus. Przeciążone wersje dla precyzji pojedynczej, podwójnej i rozszerzonej).
- Ceil32 (Zwraca największą prawie 32-bitową liczbę całkowitą.)
- Ceil64 (Zwraca największą prawie 64-bitową liczbę całkowitą).
- CharPos (Wyszukuje pierwsze wystąpienie znaku w ciągu znaków. Zwraca pozycję tego wystąpienia).
- CharPosIEx (Wyszukiwanie bez uwzględniania wielkości liter dla pierwszego wystąpienia znaku Char w ciągu, począwszy od indeksu przekazanego jako parametr. Zwraca pozycję tego wystąpienia).
- CharPosEy (Wyszukuje n-te wystąpienie znaku Char w łańcuchu, począwszy od indeksu przekazanego jako parametr. Zwraca pozycję tego wystąpienia).
- CharPosRev (wyszukuje ostatnie wystąpienie znaku w ciągu znaków. Zwraca pozycję tego wystąpienia).
- CompareMem (Porównuje dwa bloki pamięci).
- CompareStr (porównuje dwa ciągi znaków typu AnsiString.)
- CompareText (Porównuje dwa ciągi.)
- Fillchar (Wypełnia sekcję bufora pamięci tym samym bajtem lub znakiem FillValue FillCount razy.)
- Floor32 (Zwraca najmniejszą prawie 32-bitową liczbę całkowitą.)
- Floor64 (Zwraca najmniejszą prawie 64-bitową liczbę całkowitą).
- GCD32 (największy wspólny dzielnik 32-bitowy)
- IDCT (odwrotna dyskretna transformata kosinusowa)
- Int64Div (Dzieli dwie 64-bitowe liczby całkowite)
- Int64Mul (mnoży dwie 64-bitowe liczby całkowite)
- IntToStr (Konwertuje liczbę całkowitą na ciąg znaków)
- IsPrime (testuje 32-bitową liczbę całkowitą pod kątem pierwszości)
- LowerCase (Konwertuje ciąg znaków na małe litery)
- MaxFP (zwraca maksymalnie dwie wartości zmiennoprzecinkowe Single, Double lub Extended)
- MaxInt (Zwraca maksimum z dwóch wartości całkowitych)
- MaxInt64 (Zwraca maksymalnie dwie 64-bitowe wartości całkowite)
- Menedżer pamięci
- MinFP (zwraca co najmniej dwie wartości zmiennoprzecinkowe Single, Double lub Extended)
- MinInt (zwraca co najmniej dwie wartości całkowite)
- MinInt64 (Zwraca co najmniej dwie 64-bitowe wartości całkowite)
- Przenieś (Kopiuje N bajtów ze źródła do miejsca docelowego)
- Dodawanie liczb zespolonych biegunowych
- Polarne odejmowanie liczb zespolonych
- Biegunowe mnożenie liczb zespolonych
- Podział liczb zespolonych biegunowych
- Konwersja formatu biegunowego na prostokątny
- Pos (wyszukuje pierwsze wystąpienie podłańcucha w łańcuchu. Zwraca pozycję tego wystąpienia).
- PosEx (wyszukuje pierwsze wystąpienie podłańcucha w łańcuchu, zaczynając od indeksu przekazanego jako parametr. Zwraca pozycję tego wystąpienia.)
- PosIEx (Wyszukiwanie bez rozróżniania wielkości liter dla pierwszego wystąpienia podłańcucha w łańcuchu, począwszy od indeksu przekazanego jako parametr. Zwraca pozycję tego wystąpienia.)
- Potęga (Zwraca podstawę podniesioną do wykładnika)
- Prostokątne dodawanie liczb zespolonych
- Prostokątne odejmowanie liczb zespolonych
- Prostokątne mnożenie liczb zespolonych
- Prostokątny podział liczb zespolonych
- Konwersja formatu prostokątnego na biegunowy
- RGBA do BGRA (konwersja formatu mapy bitowej)
- Zaokrąglenie (bankowcy zaokrąglają wartość pojedynczą, podwójną lub rozszerzoną. Zwraca 64-bitową liczbę całkowitą)
- RoundToEx (zaokrągla a, wartość zmiennoprzecinkową o rozszerzonej precyzji do określonej cyfry lub potęgi dziesięciu przy użyciu „zaokrąglania bankiera”).
- Round32 (bankowcy zaokrąglają wartość pojedynczą, podwójną lub rozszerzoną. Zwraca 32-bitową liczbę całkowitą)
- Skalowanie w dół (skalowanie mapy bitowej)
- Sortować
- StrComp (porównuje dwa łańcuchy zakończone znakiem NULL, z uwzględnieniem wielkości liter)
- StrCopy (Kopiuje jeden łańcuch zakończony znakiem NULL do innego)
- StrICp (porównuje dwa łańcuchy zakończone znakiem null, bez uwzględniania wielkości liter)
- StrLen (zwraca długość łańcucha zakończonego zerem)
- StrLComp (porównuje dwa łańcuchy zakończone zerem do długości, z uwzględnieniem wielkości liter)
- StrLIComp (porównuje dwa łańcuchy zakończone zerem do długości, bez uwzględniania wielkości liter)
- StrToInt32 (Konwertuje łańcuch na 32-bitową liczbę całkowitą)
- Przytnij (usuwa spacje i znaki kontrolne z początku i końca ciągu)
- TList.Sort
- Trunc (obcina wartość pojedynczą, podwójną lub rozszerzoną. Zwraca 64-bitową liczbę całkowitą)
- Trunc32 (obcina wartość pojedynczą, podwójną lub rozszerzoną. Zwraca 32-bitową liczbę całkowitą)
- UpperCase (Konwertuje ciąg znaków na wielkie litery)
- Wal
Wkład do Delphi RTL
Funkcje FastCode zawarte w Delphi RTL:
- Delphi 2005: Porównaj tekst, Int64Div i FillChar
- Delphi 2006: CompareText, Int64Div i FillChar, menedżer pamięci FastMM4
- Delphi 2007 — Delphi XE: ArcCos, ArcSin, Power, PosEx, Move, Memory Manager, FillChar, Pos, __lldiv, LowerCase, UpperCase, CompareStr, CompareMem, CompareText, StrLen, StrCopy, StrComp.
Mastering Delphi autorstwa Marco Cantu zawierają rozdział o FastCode, w którym wymieniono wkład w Delphi RTL.
Biblioteka FastCode
Wszyscy zwycięzcy wyzwania są uwzględnieni w bibliotece FastCode ( http://fastcode.sourceforge.net/challenge_content/rtl_replcmnt_pkg.html ). Ta biblioteka jest open source , wydana na licencji MPL . Biblioteki można używać na dwa sposoby: 1) bezpośrednio wywołując funkcje i 2) używając funkcji łatania.
W przypadku bezpośredniego wywoływania funkcji całkowicie od twórcy aplikacji zależy wywołanie wersji funkcji, którą uważa za najszybszą.
Podczas korzystania z funkcji łatania biblioteka automatycznie wykrywa typ procesora podczas ładowania aplikacji i wykorzystuje te informacje do przekierowania wszystkich wywołań funkcji do funkcji zwycięzcy FastCode dla tego konkretnego procesora.
Menedżer pamięci FastMM4
Menedżer pamięci FastMM używany przez Delphi i C++ Builder od 2006 roku jest także zwycięzcą konkursu FastCode. Zastąpił on standardowego menedżera pamięci Delphi i jest nie tylko mniej podatny na fragmentację pamięci, ale także zapewnia ulepszone możliwości debugowania, takie jak możliwość zgłaszania wycieków pamięci podczas zamykania aplikacji, wykrywania użycia po zwolnieniu pamięci lub podwójnych wydań.
FastMM4 jest również używany jako menedżer pamięci dla aplikacji opracowanych w Lazarusie.
FastMM4 jest często wymieniany jako narzędzie „must have” dla programistów Delphi.
Nexus DB jest wyposażony w integrację FastMM4 do sprawdzania szczelności.
Użycie FastMM jest udokumentowane w „The New Memory Manager In BDS 2006”.
Aplikacje korzystające z FastCode
Aplikacja stworzona w Delphi lub C++ Builder zazwyczaj używa domyślnego menedżera pamięci, którym jest FastMM4. Funkcje FastCode w RTL zostały wybrane jako najczęściej używane, a aplikacja będzie również zazwyczaj korzystać z niektórych z nich, zwłaszcza jeśli wykonywana jest jakakolwiek obsługa ciągów znaków. Dlatego większość aplikacji Delphi/C++ Builder będzie używać kodu opracowanego w ramach projektu FastCode. Niektóre przykłady to Skype , FL Studio i własne RAD Studio firmy Embarcadero . Blog Hallvarda opisuje FastMM4 i dlaczego jest używany jako menedżer pamięci w aplikacji "The Online Trader" .