Burada gergin iki güç vardır: Performansa Karşı Okunabilirlik.
Önce üçüncü sorunu çözelim, ama uzun çizgiler:
System.out.println("Good morning everyone. I am here today to present you with a very, very lengthy sentence in order to prove a point about how it looks strange amongst other code.");
Bunu yapmanın ve okunabilirliği korumanın en iyi yolu, dize bitiştirme kullanmaktır:
System.out.println("Good morning everyone. I am here today to present you "
+ "with a very, very lengthy sentence in order to prove a "
+ "point about how it looks strange amongst other code.");
String-sabit birleştirme derleme zamanında gerçekleşecek ve performans üzerinde hiçbir etkisi olmayacak. Satırlar okunabilir ve devam edebilirsiniz.
Şimdi, hakkında:
System.out.println("Good morning.");
System.out.println("Please enter your name");
vs.
System.out.println("Good morning.\nPlease enter your name");
İkinci seçenek önemli ölçüde daha hızlı. 2X hakkında hızlı bir şekilde önereceğim .... neden?
Çünkü çalışmanın% 90'ı (geniş bir hata payı ile) karakterleri çıktıya dökmekle ilgili değildir, ancak çıktının yazması için sabitlenmesi için ek yüke ihtiyaç vardır.
Senkronizasyon
System.out
bir PrintStream
. Tanıdığım tüm Java uygulamaları, PrintStream'i dahili olarak senkronize eder: GrepCode! .
Bunun kodunuz için anlamı nedir?
Her aradığınızda System.out.println(...)
bellek modelinizi senkronize ettiğinizde kontrol ediyor ve kilit bekliyorsunuz demektir. System.out'u çağıran diğer başlıklar da kilitlenir.
Tek iş parçacıklı uygulamalarda System.out.println()
genellikle sisteminizin IO performansı ile sınırlıdır, dosyaya ne kadar hızlı yazabilirsiniz. Çok iş parçacıklı uygulamalarda, kilitleme IO'dan daha önemli bir konu olabilir.
Flushing
Her baskı temizlendi . Bu, arabelleklerin temizlenmesine neden olur ve arabelleklere Konsol düzeyinde bir yazı tetikler. Burada yapılan çaba miktarı uygulamaya bağlıdır, ancak genel olarak, yıkama işleminin performansının yalnızca temizlenen tamponun boyutuyla ilgili küçük bir kısım olduğu anlaşılmaktadır. Bellek arabelleklerinin kirli olarak işaretlendiği yıkama ile ilgili önemli bir ek yük var, Sanal makine G / Ç vb. Bu ek yükün iki kez yerine bir kez yapılması açık bir optimizasyondur.
Bazı sayılar
Aşağıdaki küçük testi bir araya getirdim:
public class ConsolePerf {
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
benchmark("Warm " + i);
}
benchmark("real");
}
private static void benchmark(String string) {
benchString(string + "short", "This is a short String");
benchString(string + "long", "This is a long String with a number of newlines\n"
+ "in it, that should simulate\n"
+ "printing some long sentences and log\n"
+ "messages.");
}
private static final int REPS = 1000;
private static void benchString(String name, String value) {
long time = System.nanoTime();
for (int i = 0; i < REPS; i++) {
System.out.println(value);
}
double ms = (System.nanoTime() - time) / 1000000.0;
System.err.printf("%s run in%n %12.3fms%n %12.3f lines per ms%n %12.3f chars per ms%n",
name, ms, REPS/ms, REPS * (value.length() + 1) / ms);
}
}
Kod nispeten basittir, art arda çıktısı almak için kısa veya uzun bir dize yazdırır. Uzun String'in içinde birden fazla yeni satır var. Her birinin 1000 yinelemesini yazdırmanın ne kadar sürdüğünü ölçer.
Bunu unix (Linux) komut isteminde çalıştırırsam, yönlendirme STDOUT
yapar /dev/null
ve gerçek sonuçları STDERR
basarsam, aşağıdakileri yapabilirim:
java -cp . ConsolePerf > /dev/null 2> ../errlog
Çıktı (errlog'da) şöyle görünür:
Warm 0short run in
7.264ms
137.667 lines per ms
3166.345 chars per ms
Warm 0long run in
1.661ms
602.051 lines per ms
74654.317 chars per ms
Warm 1short run in
1.615ms
619.327 lines per ms
14244.511 chars per ms
Warm 1long run in
2.524ms
396.238 lines per ms
49133.487 chars per ms
.......
Warm 99short run in
1.159ms
862.569 lines per ms
19839.079 chars per ms
Warm 99long run in
1.213ms
824.393 lines per ms
102224.706 chars per ms
realshort run in
1.204ms
830.520 lines per ms
19101.959 chars per ms
reallong run in
1.215ms
823.160 lines per ms
102071.811 chars per ms
Ne anlama geliyor? Son 'stanza'yı tekrar edeyim:
realshort run in
1.204ms
830.520 lines per ms
19101.959 chars per ms
reallong run in
1.215ms
823.160 lines per ms
102071.811 chars per ms
Bu, tüm amaç ve amaçlar için, 'uzun' satırın yaklaşık 5 kat daha uzun olmasına ve birden çok yeni satır içermesine rağmen, kısa satır olarak çıktısının alınması kadar uzun sürdüğü anlamına gelir.
Uzun vadede saniye başına düşen karakter sayısı 5 kat fazla, geçen süre yaklaşık aynı ...
Diğer bir deyişle, performans göreli ölçekler numara var printlns arasında değil, neyi onlar yazdırın.
Güncelleme: / dev / null yerine bir dosyaya yönlendirirseniz ne olur?
realshort run in
2.592ms
385.815 lines per ms
8873.755 chars per ms
reallong run in
2.686ms
372.306 lines per ms
46165.955 chars per ms
Çok daha yavaş, ama oranlar aynı.