Spośród dwóch fragmentów już opublikowanych, nie chcą mówić. Zgadzam się z Willem, że prawie na pewno nie ma to znaczenia dla ogólnej wydajności twojego kodu - a jeśli tak nie jest, możesz po prostu wprowadzić zmianę i ustalić dla siebie, które jest najszybsze dla danych z JVM na twoim sprzęcie.
To powiedziawszy, prawdopodobne jest, że drugi fragment byłby lepszy, gdyby najpierw przekonwertować ciąg na tablicę znaków, a następnie wykonać iteracje na macierzy. Robienie tego w ten sposób wykonywałoby tylko narzutu String tylko raz (konwersja do tablicy) zamiast każdego wywołania. Dodatkowo, możesz przekazać tablicę bezpośrednio do konstruktora String z pewnymi indeksami, co jest bardziej wydajne niż odebranie macierzy do przekazania jej pojedynczo (która następnie zostaje przekształcona w tablicę jednoznakową):
String s = "abcdefg";
char[] chars = s.toCharArray();
for(int i = 0; i < chars.length; i++) {
newFunction(String.valueOf(chars, i, 1));
}
Ale aby wzmocnić mój pierwszy punkt, kiedy patrzysz na to, czego tak naprawdę unikasz przy każdym wywołaniu String.charAt()
- to są dwa sprawdzenia graniczne, (leniwy) Boolowski OR i dodatek. Nie spowoduje to zauważalnej różnicy. Ani nie jest różnica w konstruktorach String.
Zasadniczo, oba idiomy są w porządku pod względem wydajności (nie jest to oczywiście oczywiście nieefektywne), więc nie powinieneś poświęcać więcej czasu na pracę nad nimi, chyba że profiler wykaże, że zajmuje to dużą ilość środowiska wykonawczego twojej aplikacji.I nawet wtedy prawie na pewno można uzyskać większy wzrost wydajności poprzez restrukturyzację kodu pomocniczego w tym obszarze (na przykład, aby newFunction
potraktować cały ciąg); java.lang.String jest dość dobrze zoptymalizowany pod tym kątem.
W miarę przesuwania tego ciągu należy zmienić nieco test w pierwszym teście. {char [] s = "abcdefg" .toCharArray();} powinno być wewnątrz pętli lub nawet lepiej (aby zapobiec sprytnej optymalizacji przez maszynę JVM, umieść całą pętlę i .toCharArray(), w oddzielnej funkcji). Ważne jest zmierzenie wszystkich początkowych kosztów ogólnych, a także kosztów pętli. Zwłaszcza, że wydajność może realistycznie przechodzić od jednego do drugiego w oparciu o długość struny. Dlatego ważne jest również testowanie różnych długości użądlenia. – MatBailie
+1 za rzeczywiste udzielenie odpowiedzi na pytanie. – gustafc
Przeniesiono "s" wewnątrz pętli i dodano assert(), aby zapobiec optymalizacji JVM newFunction(). Oczywiście jest teraz wolniej, ale względne pomiary są nadal takie same. Chodzi mi tylko o to, że istnieją możliwości optymalizacji, jeśli problem jest dokładnie znany. Nie chodzi o to, aby zmienić funkcję, która ma być używana dla określonej operacji, ale aby zobaczyć operację na wyższym poziomie, aby uzyskać ulepszenia, np. przez buforowanie – mhaller