Autor Wątek: Testowanie szybkości funkcji  (Przeczytany 3132 razy)

Offline MatlertheGreat

  • Użytkownik

# Styczeń 18, 2016, 21:58:07
Znalazłem w swojej gierce bardzo wolną funkcję i chciałbym przetestować kilka alternatyw dla niej. W jaki sposób robi się takie testy? Nie chodzi mi tutaj o samo mierzenie szybkości, bo z tym sobie poradzę. Mam problem z "wyciągnięciem" pojedynczej funkcji z aplikacji i testowaniem tylko jej, nie całego programu.

Trochę mozolne jest kopiowanie kodu linijka po linijce, biorąc pod uwagę wszystkie zależności w programie. Da się jakoś "podpiąć" tester pod istniejący już kod?

Offline Mr. Spam

  • Miłośnik przetworów mięsnych

Offline Kos

  • Użytkownik
    • kos.gd

# Styczeń 18, 2016, 22:16:22
Ogólnie:

- wyciągasz funkcję do osobnego pliku: foo.cpp
- piszesz sobie gdzieś na boku main() który odpala tę funkcję z jakimiś sensownymi danymi (tester.cpp)
- piszesz alternatywne implementacje dla funkcji (foo2.cpp, foo3.cpp)
- kompilujesz osobno
g++ foo.cpp tester.cpp -O tester_foo
g++ foo2.cpp tester.cpp -O tester_foo2
g++ foo3.cpp tester.cpp -O tester_foo3
- patrzysz który tester chodzi szybciej

Ew. zamiast osobnych plików możesz mieć wszystkie implementacje w 1 pliku i wybierać konkretną przez preprocesor, a potem podać mu opcję przez flagę kompilacji -D.

Offline MatlertheGreat

  • Użytkownik

# Styczeń 18, 2016, 22:26:34
Ok, ale ja właśnie mam problem z krokiem 1.
Cytuj
wyciągasz funkcję do osobnego pliku: foo.cpp
Problematyczna funkcja tworzy model terenu i nie mogę skopiować tylko tej funkcji. Razem z nią musiałbym jeszcze przeciągnąć implementację np. wierzchołków, matematykę macierzy i jakieśtam rzeczy rozsiane po całym programie1..

I zastanawiam się, czy mogę testować funkcję pozostawiając ją na swoim docelowym miejscu?

Ad.1 Nie, nie mam aż takiego spaghetti, ale moja funkcja pociągnęłaby za sobą przynajmniej 3 klasy, jak np. klasa wektora

Offline ShadowDancer

  • Redaktor

# Styczeń 18, 2016, 23:15:54
To w C++ nie ma jakiegoś fajnego profilera?

Offline MatlertheGreat

  • Użytkownik

# Styczeń 18, 2016, 23:28:47
Visual Studio 2015, którego używam, ma fajne narzędzia do profilowania całej apki i dzięki temu znalazłem najwolniejszą funkcję. Ale do testów przydałoby się wołanie funkcji kilkaset razy dla różnych scenariuszy, zrobienie z tego jakiegoś w miarę automatycznego procesu i może jakiś raport pod koniec. Wszystko to mogę napisać, ale muszę mieć dostęp do funkcji. A nie wiem jak to osiągnąć bez zbytniego rozdrabniania programu. Może coś pomijam i da się to zrobić w visualu?

Mógłbym rozbić "silnik" gry na oddzielne libki i z nich testować funkcję. Czy to dobre rozwiązanie? O czymś podobnym z google wyczytałem.
« Ostatnia zmiana: Styczeń 18, 2016, 23:34:42 wysłana przez MatlertheGreat »

Offline ShadowDancer

  • Redaktor

# Styczeń 19, 2016, 02:33:55
Wydziel interfejsy dla zależności z których korzysta funkcja i w testach użyj jakichś jakich "fake" class (zwracających predefiniowane dane testowe).
Jeśli masz jakieś statyczne zależności, których nie możesz użyć w testach to wydzielasz z nich interfejsy i pakujesz w klasę np. renderContext i jak wyżej.


Wszystko co napisałem odnosi się do testowania obiektu (obiekt ma pewne zależności, które możesz w testach zastąpić).

Offline yarpen

  • Użytkownik

# Styczeń 19, 2016, 03:13:41
__rdtsc przed wywolaniem f-kcji, __rdtsc po wywolaniu, odjecie i wypisanie wyniku.
Zerknij tez np na https://www.youtube.com/watch?v=uHSLHvWFkto

Offline fenbf

  • Użytkownik
    • Code and Graphics

# Styczeń 19, 2016, 10:07:37
jeśli dobrze rozumiem to chodzi Ci o robienie microbenchmarków dla danego modułu.

ostatnio natknąłem się na bibliotekę https://nonius.io/ lub hayai (https://bruun.co/2012/02/07/easy-cpp-benchmarking)

są to biblioteki które pozwalają Ci robić benchmarki w stylu unit testów, do tego jest fajny runner.
Ale żeby to w ogóle miało sens, trzeba dobrze wyekstrachować interfejsy/moduł, mieć powtarzalne testy i także aby optymalizator nie usunął Twojego kodu.

Offline MatlertheGreat

  • Użytkownik

# Styczeń 19, 2016, 15:46:56
Dzięki, bardzo przydadzą się biblioteki i filmik też obejrzę. Ale chyba niedokładnie wyjaśniłem mój problem.
Wydziel interfejsy dla zależności z których korzysta funkcja i w testach użyj jakichś jakich "fake" class
A co jeśli będę chciał przetestować inną funkcję? Musiałbym dokładać kolejne zależności do testera.
Ale żeby to w ogóle miało sens, trzeba dobrze wyekstrachować interfejsy/moduł.
Nie wiem jak to zrobić i dla tego pytam tutaj. Nie chodzi o mierzenie czasu i wyświetlanie wyników tylko o dostęp do funkcji jednego programu z drugiego. Chciałbym aby testy uruchamiane były zupełnie oddzielnie, a aplikacja "właściwa" nawet o nich nie wiedziała. Mogłem nawet nie wspominać o testowaniu tylko zapytać się jak wywołać funkcję z programu A w programie B ;p.

Offline yarpen

  • Użytkownik

  • +1
# Styczeń 19, 2016, 18:17:44
Szczerze mowiac to dosyc dziwne podejscie. Najbardziej dokladne wyniki dostaniesz testujac alternatywy w samej grze, a nie poza nia.

Offline Xion

  • Moderator
    • xion.log

# Styczeń 19, 2016, 18:22:51
Cytuj
Ale do testów przydałoby się wołanie funkcji kilkaset razy dla różnych scenariuszy, (...)
Niezupełnie. O ile nie piszesz biblioteki do szerszego rozpowszechniania, twoim celem powinno być zoptymalizowanie efektywności całego programu. Inaczej może się na przykład okazać, że poprawa jednej funkcji w izolacji pogorszy całą charakterystykę wydajnościową aplikacji, bo chociażby będzie ona zużywała więcej pamięci.

Zbierz dane o czasie wywołania funkcji dla rzeczywistych scenariuszy w twojej aplikacji. Najlepiej byłoby to zrobić pisząc odpowiednie testy, żeby potem łatwo było je reprodukować i sprawdzać efektywność wprowadzanych optymalizacji. Oczywiście możesz taki scenariusz wywoływać N razy w celu minimalizacji jakichś losowych fluktuacji, ale powinno być to zawsze w kontekście całego programu.

Offline CheshireCat

  • Użytkownik

# Styczeń 19, 2016, 18:25:49
Nie możesz sobie sklonować całego kodu i testować bezpośrednio dwóch wariantów jednocześnie? A potem wygrany wariant do następnej fazy z kolejnym innym wariantem? No chyba, że chcesz to zautomatyzować bo masz za dużo "alternatyw" zaimplementowania tej funkcji.

Mógłbyś sobie mierzyć czas wywołania funkcji, zbierać w jakiejś kolekcji w programie i appendować do pliku przy zamknięciu programu. Odpalasz kilka razy, porównujesz pliki, zostawiasz jednej klon gry i bierzesz na warsztat kolejny...

Offline ShadowDancer

  • Redaktor

# Styczeń 19, 2016, 19:31:14
Jeżeli coś optymalizujemy przez dłuższy czas, to zrobienie jakiegoś jarzma to testów to podstawa, inaczej może nas szlag trafić, gdy za każdym raziem np. ładujemy level, albo przeklikujemy menu. Zakładamy, że op np. testuje ułożenie danych/macierzy w pamięci np. podczas odpalania updateowania tysięcy obiektów, albo coś w tym stylu.

Offline MatlertheGreat

  • Użytkownik

# Styczeń 19, 2016, 22:06:46
Ok, myślałem, że wydzielenie funkcji będzie dobrym pomysłem. Ale skoro tak się raczej nie robi to wbuduje testy do apki. Dzięki za rady ;)

Offline Xion

  • Moderator
    • xion.log

# Styczeń 20, 2016, 03:23:52
Off-topic

Cytuj
jarzma to testów
Cudowne tłumaczenie "test harness" :D