Perl to język o dynamicznej typizacji i dużej elastyczności, co często prowadzi do niejawnych kosztów wydajności przy niewłaściwym użyciu. Optymalizacja wydajności jest nieodłączną częścią utrzymania średnich i dużych skryptów.
Od samego początku Perl był ukierunkowany na szybkość prototypowania i szybką integrację bibliotek. Rzeczywista optymalizacja pojawiła się po kilku latach - wraz z przybyciem modułów profilujących (Devel::DProf, NYTProf), analizy alokacji i pojawienia się ogólnie przyjętych najlepszych praktyk.
Główne wąskie gardła pojawiają się z powodu niekontrolowanego wzrostu struktur, niepotrzebnych alokacji, częstego kopiowania danych i nieoczywistych cech działania interpretera Perl - na przykład niewłaściwego użycia zmiennych globalnych i nieefektywnych wyrażeń regularnych.
perl -d:NYTProf script.pl, po czym raporty są analizowane przez nytprofhtmlundefPrzykład kodu: - porównanie inline map z prostą pętlą:
my @data = (1..1_000_000); my @result = map { $_ * 2 } @data; # potencjalnie wolniejsze przy skomplikowanych obliczeniach # vs my @result; foreach (@data) { push @result, $_ * 2; }
Czy zawsze użycie map jest szybsze niż foreach?
Nie. Dla najprostszych manipulacji na krótkich tablicach różnice są minimalne, ale skomplikowane wyrażenia lub praca z dużymi tablicami może spowolnić z powodu tymczasowych list map. W foreach można ręcznie kontrolować pamięć.
Czy autovivification wpływa na wydajność?
Tak, szczególnie przy przypadkowym tworzeniu dużych zagnieżdżonych struktur. Automatyczne tworzenie nowych poziomów może szybko wyczerpać pamięć, jeśli przypadkowo uzyska się dostęp do nieinicjowanego hasha w głębi struktury.
Czy konieczne jest wcześniejsze deklarowanie zmiennych przez my dla przyspieszenia?
Tak, ale nie zawsze w celu przyspieszenia - zmienne lokalne częściej trafiają do szybkiego dostępu Perl niż globalne, jednak rzeczywisty zysk zależy od rozmiaru programu i liczby odwołań.
Przykład:
my $sum = 0; foreach my $x (@big_array) { $sum += $x; }
W dużym skrypcie ETL logi są przetwarzane przez map na milionach rekordów z zagnieżdżonymi wyrażeniami regularnymi. Skrypt zjada pamięć operacyjną i idzie do swapu po 20 minutach pracy.
Zalety:
Wady:
Przeprowadzono profilowanie, dodano jawne pętle, wyrażenia regulare podzielono na etapy, wszystkie duże tablice przerobiono na referencje. Czas pracy skryptu skrócił się dwukrotnie, zużycie pamięci - dziesięciokrotnie.
Zalety:
Wady: