Pytanie Dlaczego drukowanie "B" jest znacznie wolniejsze niż drukowanie "#"?


Wygenerowałem dwie macierze 1000 x 1000:

Pierwsza matryca: O i #.
Drugi Macierz: O i B.

Przy użyciu poniższego kodu pierwsza matryca zajęła 8,52 sekundy:

Random r = new Random();
for (int i = 0; i < 1000; i++) {
    for (int j = 0; j < 1000; j++) {
        if(r.nextInt(4) == 0) {
            System.out.print("O");
        } else {
            System.out.print("#");
        }
    }

   System.out.println("");
 }

Z tym kodem druga matryca zajęła 259.152 sekund:

Random r = new Random();
for (int i = 0; i < 1000; i++) {
    for (int j = 0; j < 1000; j++) {
        if(r.nextInt(4) == 0) {
            System.out.print("O");
        } else {
            System.out.print("B"); //only line changed
        }
    }

    System.out.println("");
}

Jaki jest powód dramatycznie odmiennych czasów uruchomienia?


Jak sugerowano w komentarzach, tylko drukowanie System.out.print("#"); trwa 7.8871 sekund, podczas gdy System.out.print("B"); daje still printing....

Jak inni, którzy zauważyli, że działa dla nich normalnie, próbowałem Ideone.com na przykład, obie części kodu wykonują z tą samą prędkością.

Test kondycji:

  • Sprawdziłem ten test Netbeans 7.2, z wyjściem do swojej konsoli
  • użyłem System.nanoTime() do pomiarów

2417
2018-02-21 23:45


pochodzenie


Spróbuj zmienić rand.nextInt (4) == 0 na i <250, aby wyeliminować efekt losowego generatora. Możesz zabraknąć entropii, która spowalnia generację losową - fejese
Oba wydają się działać przez tyle samo czasu na moim komputerze, ~ 4 sekundy. - Sotirios Delimanolis
jeśli sugerujesz, że drukowanie B zajmuje więcej czasu niż drukowanie # ... dlaczego nie próbujesz wydrukować wszystkich B & wszystkich # zamiast polegać na zmiennej losowej r - Kakarot
Na podstawie przyjętej odpowiedzi najwyraźniej nie próbowałem uruchamiać go z wyjściem przekierowanym do pliku lub / dev / null. - Barmar
@fejese, Random () nie jest kryptograficznym rng, więc nie wykorzystuje puli entropii. - Divide


Odpowiedzi:


Czysta spekulacja jest to, że używasz terminalu, który próbuje zrobić zawijanie słów zamiast pakowania postaci i smakołyków B jako znak słowny, ale # jako nie-słowny charakter. Kiedy osiąga koniec linii i szuka miejsca, w którym mógłby przerwać linię, widzi a # niemal natychmiast i szczęśliwie się tam włamuje; mając na uwadze, że z B, musi dalej szukać i może mieć więcej tekstu do zawinięcia (co może być kosztowne w niektórych terminalach, np. wyprowadzanie tylnych przestrzeni, a następnie wyprowadzanie spacji w celu nadpisania zawijanych liter).

Ale to czysta spekulacja.


3721
2018-04-03 15:01



To jest właściwie poprawna odpowiedź! Dodawanie spacji po B rozwiązuje to. - Kuba Spatny
Istnieją pewne odpowiedzi, które wynikają z ciężko nabytego doświadczenia. T.J. a ja (odkąd jesteśmy przyjaciółmi) dorastaliśmy w czasach Apple] [i zx80 / ​​81. Wtedy nie było wbudowanego w słowo zawijania. Więc oboje skończyliśmy pisać własne - więcej niż raz. I te lekcje trzymają się ciebie, zostają spalone w twoim jaszczurczym mózgu. Ale jeśli pochyliłbyś się do kodowania po tym, kiedy słowo otoczenie zawija wszystko, lub robisz to ręcznie przed uruchomieniem, trudniej jest napotkać problemy z zawijaniem słów. - JockM
Genialna dedukcja. Ale powinniśmy uogólnić na tej lekcji i zawsze mierzyć wydajność z wyjściem albo wyeliminowanym, skierowanym do / dev / null (NUL na Windows) albo przynajmniej do pliku. Wyświetlanie na jakiejkolwiek konsoli jest generalnie bardzo kosztownym IO i zawsze zniekształca czasy - nawet jeśli nie jest tak drastycznie mylące jak to. - Bob Kerns
@MrLister: System.out.println nie tworzy zawinięcia; rzeczą, na którą to wypuszczano było wykonywanie zawijania słów (i blokowanie) System.out.println musiałem czekać). - T.J. Crowder
@Chris - faktycznie, będę argumentował, że nie drukowanie ich jest rozwiązaniem problemu dokładnego czasu algorytmu. Za każdym razem, gdy drukujesz do konsoli (dowolnego rodzaju), wywołujesz wszystkie zewnętrzne przetwarzanie niezwiązane z testowaniem wydajności. To błąd w twojej procedurze pomiarowej, czysty i prosty. Z drugiej strony, jeśli postrzegasz problem nie jako pomiar, ale ze zrozumieniem rozbieżności, to tak, nie drukowanie jest sztuczką debugującą. Sprowadza się do tego, którego problemu próbujesz rozwiązać? - Bob Kerns


Przeprowadziłem testy Eclipse vs Netbeans 8.0.2, oba z wersją Java 1.8; użyłem System.nanoTime() do pomiarów.

Zaćmienie:

mam w obu przypadkach - na około 1,564 sekundy.

Netbeans:

  • Za pomocą "#": 1,536 sekundy
  • Używając "B": 44,164 sekundy

Wygląda na to, że Netbeans ma złą wydajność na wydruku na konsolę.

Po kolejnych badaniach zdałem sobie sprawę, że problem jest zawijanie linii maksymalnego bufora Netbeans (nie ogranicza się do System.out.println command), wykazane przez ten kod:

for (int i = 0; i < 1000; i++) {
    long t1 = System.nanoTime();
    System.out.print("BBB......BBB"); \\<-contain 1000 "B"
    long t2 = System.nanoTime();
    System.out.println(t2-t1);
    System.out.println("");
}

Wyniki czasowe są mniejsze niż 1 ms dla każdej iteracji z wyjątkiem co piąta iteracja, gdy wynik czasu wynosi około 225 milisekund. Coś jak (w nanosekundach):

BBB...31744
BBB...31744
BBB...31744
BBB...31744
BBB...226365807
BBB...31744
BBB...31744
BBB...31744
BBB...31744
BBB...226365807
.
.
.

I tak dalej..

Podsumowanie:

  1. Eclipse działa idealnie z "B"
  2. Netbeans ma problem z owijaniem wiersza, który można rozwiązać (ponieważ problem nie występuje w środowisku Eclipse) (bez dodawania spacji po B ("B")).

148



czy możesz rozwinąć swoje strategie badawcze i co ostatecznie doprowadziło cię do odkrycia, że ​​zawinięcie linii było sprawcą? (jestem ciekawa twoich umiejętności detektywistycznych!) - silph