Jeśli zrozumiesz, w jaki sposób działa architektura PyPy, przekonasz się, że próba wskazania poszczególnych linii kodu nie jest tak naprawdę wydajna. Zaczynasz od interpretera Pythona napisanego w RPython, który następnie przechodzi przez JIT śledzący, który generuje wykresy przepływu, a następnie transformuje te wykresy w celu optymalizacji interpretera RPython. Oznacza to, że układ kodu Pythona uruchamianego przez interpreter języka RPython będącego JIT może mieć bardzo odmienną strukturę niż faktycznie zoptymalizowany asembler. Ponadto należy pamiętać, że JIT zawsze działa w pętli lub funkcji, więc uzyskiwanie statystyk liniowych nie ma takiego znaczenia. W związku z tym myślę, że cProfile
może być dobrym rozwiązaniem dla Ciebie, ponieważ pozwoli Ci zorientować się, gdzie skoncentrować optymalizację. Kiedy już wiesz, które funkcje są wąskimi gardłami, możesz poświęcić wysiłki optymalizacyjne na te wolniejsze funkcje, zamiast próbować naprawić pojedynczą linię kodu Pythona.
Należy pamiętać, że PyPy ma bardzo różne właściwości wydajności niż cPython. Zawsze staraj się pisać kod w tak prosty sposób, jak to tylko możliwe (to nie znaczy tak mało jak to możliwe). Istnieje kilka innych heurystyk, które pomagają w takich sytuacjach, jak używanie wyspecjalizowanych list, używanie obiektów przez dyktowanie, gdy masz niewielką liczbę w większości stałych kluczy, unikanie rozszerzeń C przy użyciu API Python, itp.
Jeśli naprawdę, naprawdę nalegasz o próbach optymalizacji na poziomie linii. Istnieje kilka opcji. Jedna z nich nazywa się JitViewer (https://bitbucket.org/pypy/jitviewer), co pozwala uzyskać bardzo niski poziom tego, co robi JIT z twoim kodem. Na przykład możesz nawet zobaczyć instrukcje asemblera, które odpowiadają pętli Pythona. Korzystając z tego narzędzia, możesz naprawdę zrozumieć, jak szybko PyPy będzie się zachowywać z pewnymi częściami kodu, ponieważ teraz możesz robić głupie rzeczy, takie jak liczba instrukcji asemblera użytych w pętli lub coś takiego.
Jaka jest Twoja sugestia? –
Moja sugestia polegała na użyciu cProfile, biorąc pod uwagę, jak PyPy faktycznie działa. Moją drugą sugestią było użycie JitViewer, jeśli naprawdę potrzebujesz niskiego poziomu zrozumienia cech wydajności twojego kodu. – jlund3
Transformacje wykresów przepływu są stosowane podczas kompilowania i optymalizacji kodu RPython implementującego samego interpretera, * nie * Twojego kodu Pythona. Transformacje te są odpowiednikiem transformacji, które kompilator C stosuje do kodu C interpretera CPython, i nie mają nic wspólnego z kodem Pythona użytkownika końcowego. JIT PyPy przedstawia jednak problem, o którym mówisz; gorące pętle będą prawdopodobnie kompilowane przez JIT do wielu różnych bloków kodu zespołu, co sprawia, że mapowanie wydajności z powrotem do indywidualnych instrukcji Pythona jest trudne. – Ben