Питання Чому друк "B" різко повільніше, ніж друк "#"?


Я створив дві матриці 1000 х 1000:

Перша матриця: O і #.
Друга Матриця: O і B.

Використовуючи наступний код, перша матриця зайняла 8,52 секунди для завершення:

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("");
 }

За допомогою цього коду друга матриця зайняла 259,152 секунди, щоб завершити:

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("");
}

Яка причина різко різних часів роботи?


Як пропонувалося в коментарях, тільки друкувати System.out.print("#"); бере 7.8871 секунд, в той час як System.out.print("B"); дає still printing....

Як і інші, які вказали, що це нормально працює для них, я намагався Ideone.com наприклад, і обидва частини коду виконуються з однаковою швидкістю.

Умови випробувань:

  • Я випробував це випробування Netbeans 7.2, з виходом на його консоль
  • я використав System.nanoTime() для вимірювань

2417
2018-02-21 23:45


походження


Спробуйте змінити rand.nextInt (4) == 0 до i <250 для усунення ефекту випадкового генератора. Ви можете закінчити ентропію, яка сповільнює випадкове покоління - fejese
Обидва, здається, запускаються на той самий час на моїй машині ~ 4 секунди. - Sotirios Delimanolis
якщо ви припускаєте, що друк B займає більше часу, ніж друк # .... чому ви не намагаєтеся надрукувати всі B і всі #, а не покладатися на випадкову величину r - Kakarot
Виходячи з прийнятої відповіді, ви, напевно, не спробували запустити його з вихідним переспрямуванням у файл або / dev / null. - Barmar
@fejese, Random () не є криптографічним rng, тому не використовує пул ентропії. - Divide


Відповіді:


Чисті міркування це те, що ви використовуєте термінал, який намагається зробити словотворення а не персонаж-обгортка, а лікує B як символ слова але # як символ не слова. Таким чином, коли він досягає кінця рядка та шукає місце для розриву рядка, він бачить a # майже відразу і щасливо розбивається там; тоді як з B, він повинен продовжувати шукати довше, і може мати більше тексту для обгортання (що може бути дорогим на деяких терміналах, наприклад, виводячи зворотні пробіли, а потім виводити пробіли, щоб переписати букви, що обертаються).

Але це чисті спекуляції.


3721
2018-04-03 15:01



Насправді це правильна відповідь! Додавання пробілу після B вирішує це. - Kuba Spatny
Є кілька відповідей, які надходять з насиченого досвіду. Т.Ж. і я (оскільки ми друзі) виросла в дні Apple] [і zx80 / ​​81. Тоді не було вбудованого словотвору. Таким чином, ми обидва в кінцевому підсумку писали наші власні - неодноразово. І ці уроки прилипнуть до вас, вони спалюються до мозку ящірки. Але якщо ви покладетеся до коду після цього, коли ваше слово середовища затінює все, або ви робите це вручну перед виконанням, важче зіткнутися з проблемами зі словосполученням. - JockM
Блискучий відрахування. Але ми повинні узагальнювати з цього уроку, і завжди вимірювати продуктивність з виведенням або усувати, спрямовані на / dev / null (NUL на Windows) або, принаймні, у файл. Відображення на будь-якому консолі, як правило, є дуже дорогим IO, і завжди спотворює таймінги - навіть якщо не так різко заплутано, як це. - Bob Kerns
@ MrLister: System.out.println не робить словотворення; справа, яку вона виводила, робила словотворення (і блокування, так System.out.println довелося чекати). - T.J. Crowder
@ Chris - насправді, я стверджую, що не друкувати їх є рішення, до проблеми отримання точних таймінгів алгоритму. Кожен раз, коли ви надруковуєте консоль (будь-якого роду), ви запускаєте будь-яку зовнішню обробку, не пов'язану з тим, що ви тестуєте продуктивність. Це помилка у вашій процедурі вимірювання, чиста і проста. З іншого боку, якщо ви розглядаєте проблему не як вимірювання, а розумієте невідповідність, то так, а не друк є налагоджувальним трюком. Здається, яку проблему ви намагаєтеся вирішити? - Bob Kerns


Я виконував тести на Eclipse проти Netbeans 8.0.2, як з версією Java версії 1.8; я використав System.nanoTime() для вимірювань.

Eclipse:

Я отримав одночасно в обох випадках - навколо 1.564 секунди.

Netbeans:

  • Використання "#": 1,536 секунд
  • Використання "B": 44,164 секунди

Таким чином, схоже, Netbeans має погану продуктивність на друк для консолі.

Після ще кількох досліджень я зрозумів, що проблема лінія обгортання максимального буфера Netbeans (це не обмежується System.out.println команда), продемонстрований цим кодом:

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("");
}

Результати часу менше, ніж 1 мілісекун за кожну ітерацію крім кожна п'ята ітерація, коли результат часу становить близько 225 мілісекунд. Щось подібне (у наносекундах):

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

І так далі..

Підсумок:

  1. Eclipse ідеально працює з "B"
  2. Netbeans має лінійну обгорткову проблему, яку можна вирішити (оскільки проблема не відбувається в eclipse) (без додавання простору після B ("B")).

148



Чи можете ви розповісти про свої стратегії дослідження, а потім, що нарешті призвело вас до висновку, що лінійний обгортки був винуватцем? (я цікавлюся вашими дієтичними навичками, тобто!) - silph