W sekcji Kiedy stosować wyjątek w The Pragmatic Programmer , książka pisze, że zamiast:
retcode = OK;
if (socket.read(name) != OK) {
retcode = BAD_READ;
}
else {
processName(name);
if (socket.read(address) != OK) {
retcode = BAD_READ;
}
else {
processAddress(address);
if (socket.read(telNo) != OK) {
retcode = BAD_READ;
}
else {
// etc, etc...
}
}
}
return retcode;
, oni wolą:
retcode = OK;
try {
socket.read(name);
process(name);
socket.read(address);
processAddress(address);
socket.read(telNo);
// etc, etc...
}
catch (IOException e) {
retcode = BAD_READ;
Logger.log( "Error reading individual: " + e.getMessage());
}
return retcode;
po prostu dlatego, że wygląda ładniej. Jestem wszystkim dla kodu schludny, jednak nie jest konieczne łapanie wyjątków wąskim gardłem wydajności?
Rozumiem, że powinniśmy zrezygnować z drobnej optymalizacji starszego kodu (przynajmniej 99% razy), jednak z tego, co wiem, wychwytywanie wyjątków należy do klasy kodu, która ma zauważalne opóźnienie w czasie wykonywania. Dlatego zastanawiałem się, jakie jest uzasadnienie, że drugi fragment kodu jest lepszy od pierwszego?
A raczej jaki kod wolisz?
java
exception-handling
language-agnostic
Pacerier
źródło
źródło
Odpowiedzi:
Wyjątki są zwykle wolniejsze tylko wtedy, gdy zostaną zgłoszone. Zwykle wyjątki w takich sytuacjach są rzadkie, więc nie należy się tym martwić. Powinieneś naprawdę martwić się o skuteczność wyjątków, jeśli zdarzają się one cały czas, a zatem są znaczącym czynnikiem.
Drugi kod jest lepszy, ponieważ znacznie łatwiej jest podążać za logiką. Obsługa błędów jest ładnie zlokalizowana. Jedynym zastrzeżeniem jest to, że jeśli używasz wyjątków, to używaj wyjątków. Nie wychwytuj wyjątków, a następnie zwróć kod błędu.
źródło
Cóż, jak mówią również, wyjątki powinny zajmować się wyjątkowymi przypadkami , a ponieważ jest to wyjątkowy przypadek (tj. Coś, co zdarza się rzadko i pomiędzy nimi), powiedziałbym, że dotyczy to również tutaj.
Także radzę przed mikro optymalizacji rzeczy, takich jak ten. Skoncentruj się bardziej na czytelności kodu , ponieważ będziesz spędzać znacznie więcej czasu na czytaniu kodu niż na pisaniu nowego kodu.
Aby naprawdę upewnić się, że jest to wąskie gardło w zakresie wydajności, wykonaj profilowanie oraz przeanalizuj i skoncentruj się na bardziej krytycznych zadaniach opartych na tej analizie.
źródło
Skąd to wiesz? Jak zdefiniujesz „zauważalne opóźnienie”?
Jest to dokładnie taki niejasny (i całkowicie błędny) mit wydajności, który prowadzi do bezużytecznych przedwczesnych optymalizacji.
Zgłaszanie i wyławianie wyjątku może być powolne w porównaniu do dodawania dwóch liczb, ale jest całkowicie nieistotne w porównaniu do odczytu danych z gniazda. Prawdopodobnie możesz rzucić i złapać tysiąc wyjątków w tym samym czasie, gdy czytasz pojedynczy pakiet sieciowy. Nie mówimy tu o tysiącach wyjątków, tylko o jednym.
źródło
Zgadzam się z odpowiedziami, które już otrzymałeś, mówiąc, że jest to wyjątkowy przypadek, więc rozsądnie jest użyć obsługi wyjątków.
Zajmując się sprawami dotyczącymi wydajności w bardziej bezpośredni sposób, myślę, że musisz zachować poczucie skali w różnych kwestiach. Zgłoszenie / wyłapanie wyjątku w tych okolicznościach może potrwać jeden mikrosekundę. Gdy kontrola przepływu idzie, jest to powolne - wiele razy wolniejsze niż zwykłe
if
stwierdzenia, nie ma co do tego wątpliwości.Jednocześnie pamiętaj, że to, co tu robisz, to odczytywanie danych z sieci. Przy prędkości 10 megabitów na sekundę (wolna dla sieci lokalnej, ale dość szybko w miarę połączenia z Internetem), jest to ta sama kolejność, co czas odczytania jednego bajtu informacji.
Oczywiście, narzut ten powstaje tylko wtedy, gdy faktycznie wyrzucisz wyjątek - gdy nie zostanie wyrzucony, zwykle jest on w ogóle niewielki lub wcale (przynajmniej z tego, co widziałem, najbardziej znaczący narzut nie pochodzi z sama obsługa wyjątków, ponieważ od dodania większej liczby potencjalnych przepływów kontroli, co utrudnia kompilatorowi również optymalizację).
W takim przypadku, gdy zostanie zgłoszony wyjątek, dane zostaną zapisane w dzienniku. Biorąc pod uwagę naturę rejestrowania, istnieje duże prawdopodobieństwo, że opróżnienie tego wyniku natychmiast po jego zapisaniu (aby upewnić się, że nie zostanie utracone). Zapisywanie na dysku jest (znowu) dość powolną operacją - potrzebujesz dość szybkiego dysku SSD klasy korporacyjnej, aby uzyskać nawet dziesiątki tysięcy procesorów IOP na sekundę. Dysk używany do logowania można łatwo ograniczyć do setek procesorów IOP na sekundę.
Podsumowując: są przypadki, w których narzut obsługi wyjątków może być znaczący, ale prawie na pewno nie jest to jeden z nich.
źródło