Синхронизация потоков

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by arthurfok, 14 Nov 2012.

  1. Jingo Bo

    Jingo Bo Member

    Joined:
    25 Oct 2009
    Messages:
    368
    Likes Received:
    51
    Reputations:
    7
    Я не спорю, я просто имел ввиду немного другое. Критическая секция и TThread.Synchronize это совершенно разные вещи, сравнивать их беззсмысленно и если учесть, то что добавление в очередь идет через ту же самую критическую секцию, так же используются объекты ядра(событие) - естественно скорость меньше.
     
  2. Белый Ворон

    Joined:
    7 Oct 2012
    Messages:
    46
    Likes Received:
    3
    Reputations:
    0
    я в курсе (внезапно) :)
    просто ты привел пример из своей практики, а я привел 2 момента которые говорят как раз о том, что это совсем другой случай.

    ps кстати я когда работал в дельфи, поначалу тоже записывал в лог на форме сразу через Synchronize. потом перешел на виндовые сообщения - стало побыстрее. но в итоге таки начал юзать буффер :D а сбрасывать его в лог по таймеру. оказалось что это не инди такая тормозная библиотека, а тупо неоптимизированная работа с ГУИ была :D нагрузка на CPU сразу стала заметно меньше.
    но тут, повторюсь, совсем не тот случай.
     
  3. Белый Ворон

    Joined:
    7 Oct 2012
    Messages:
    46
    Likes Received:
    3
    Reputations:
    0
    а вот мне интересно сторонники "буфферизации" забыли что буффер то тоже общий, а значит его тоже надо оборачивать в крит. секцию?

    100 строк, без буффера:
    100 lock'ов, 100 вызовов WriteLine, одна КС (на файл), потери данных нет

    с буффером:
    100 локов для буффера, 1 лок для файла, запись 100 строк (тест показал что разницы особой нету), 2 КС (одна для буффера, одна для файла), потенциальная потеря данных, усложнение кода.

    так в чем профит-то?
     
  4. Chrome~

    Chrome~ Elder - Старейшина

    Joined:
    13 Dec 2008
    Messages:
    936
    Likes Received:
    162
    Reputations:
    27
    Критическая секция для файла? Зачем? Где ты видишь потенциальную потерю данных и усложнение кода? При буферизации все строки могут записаться за 1 раз, в то время как без буферизации каждая строка будет записываться отдельно.
     
  5. Белый Ворон

    Joined:
    7 Oct 2012
    Messages:
    46
    Likes Received:
    3
    Reputations:
    0
    а что с файлом будет работать какой-то определенный поток?
    Если часть данных хранится в памяти, то при внезапной остановке программы эта часть может просто потеряться. Причин этому может быть множество. N времени зря брутили.
    с буффером кода больше получится. разве нет?
    а могут и не записаться.
    и?

    алсо, эта разница в 2 миллисекунды которую показал тест, запросто улетучивается засчет расходов на обслуживание буффера.

    что-то я опять не заметил в чем профит.
     
  6. Chrome~

    Chrome~ Elder - Старейшина

    Joined:
    13 Dec 2008
    Messages:
    936
    Likes Received:
    162
    Reputations:
    27
    Критическая секция нужна только для объекта, который выполняет вывод с буферизацией и ни для чего больше.
    С чего случаться внезапной остановке?
    Если все же произойдет что то аварийное, то в худшем случае будет утеряно 4-8 Кб. данных (размер буфера).
    Ты не знаешь, что в коде, который ты написал выше (https://forum.antichat.ru/showpost.php?p=3341500&postcount=6) выполняется вывод с буферизацией?
    Нечего сказать. В обоих случаях используется буферизация.
     
    1 person likes this.
  7. Белый Ворон

    Joined:
    7 Oct 2012
    Messages:
    46
    Likes Received:
    3
    Reputations:
    0
    свет выключили, необработанное исключение в программе, переполнение диска. да мало ли чего. причин разных могут быть десятки. а ты на авось надеешься.
    у ПО смысл такой - обработка информации. И сохранение результатов своей работы.
    если программа не может гарантировать сохранение, но при этом она с буффером - это говнопрограмма.
    если представить что средняя длина пароля в однобайтовой кодировке 10 байт, то в 8 кб поместится примерно 680 паролей. а это может быть результатом целого часа работы брутера. а за час может многое произойти. даже конец света.
    тот тест имел совсем другой смысл.

    тест
    ну вот написал тест в многопоточном режиме. работа с сетью эмулируется при помощи Thread.Sleep(). один поток записывает 1 пароль в секунду.
    создаем временный проект в VS, копируем, вставляем, запускаем без отладки.
    сравниваем среднее количество тиков на вызовы Write(password).
    сравниваем простоту реализации классов представляющих разный метод сохранения паролей.
    потом объясняем мне смысл использования буффера.

    у меня выдает одинаковую производительность на обоих способах. но с моим способом получаем простоту и стабильность, а с твоим - переусложнённость и нестабильность.
     
    #27 Белый Ворон, 23 Nov 2012
    Last edited: 23 Nov 2012
  8. Chrome~

    Chrome~ Elder - Старейшина

    Joined:
    13 Dec 2008
    Messages:
    936
    Likes Received:
    162
    Reputations:
    27
    Для начала должен сказать, что своих способов я не приводил, так что "переусложнённость и нестабильность" - это только то, что написал ты и как ты это понимаешь.
    Свет могут выключить и тогда, когда программа будет записывать данные на винт, то есть от этого не застрахован ни в каком случае. Да, когда буферизация не используется, то маловероятно что то потерять. Вообще для брутфорса буферизация результатов не столь важна, можно и без нее обойтись.

    Но дело в том, что у тебя не правильное понимание термина буферизации. Ты создаешь какие то дополнительные List'ы и синхронизируешь их, это неправильно. Зачем все это делать и зачем так извращаться, если StreamWriter делает буферизацию за тебя, даже большее: по умолчанию он уже записывает данные с буферизацией! То есть в том примере, который ты привел, оба класса используют буферизацию :) Даже больше: класс PasswordWriterWithBuffer использует ненужную двойную буферизацию.

    Посмотрим на пример работы твоего кода:
    Code:
    Брут с буффером начался. Нажмите S для останова
    s
    Записано 1459 паролей. Среднее количество тактов на вызов Write = 7
    Брут без буффера начался. Нажмите S для останова
    s
    Записано 1381 паролей. Среднее количество тактов на вызов Write = 7
    Теперь все же отключим буферизацию в твоем классе PasswordWriterBufferSucks. Для этого напишем такой конструктор
    Code:
            public PasswordWriterBufferSucks()
            {
                writer.AutoFlush = true;
            }
    И смотрим на вывод программы:
    Code:
    Брут с буффером начался. Нажмите S для останова
    s
    Записано 1633 паролей. Среднее количество тактов на вызов Write = 10
    Брут без буффера начался. Нажмите S для останова
    s
    Записано 1762 паролей. Среднее количество тактов на вызов Write = 101
    Осталось только процитировать:
    [​IMG]
     
  9. Белый Ворон

    Joined:
    7 Oct 2012
    Messages:
    46
    Likes Received:
    3
    Reputations:
    0
    а ну да, я опять забыл про AutoFlush
    погонял с разным размером буфера.
    даже с 12 байтами разница в десятки раз. увеличение буфера не дает практически прироста производительности. 12 байтjd это примерно 1 строка. следовательно это почти равнозначно работе вообще без буфера. верно?
    смысла ставить буфер 4092 вообще ноль - 12 тиков при 12 байтах и 11 при 4092 байтах.
    а значит, StreamWriter попросту не оптимизирован на построчную запись. и дело вовсе не в буферизации.
    надо глянуть исходники.
    в-общем, я буду выяснять, почему так происходит.
    почему, мать его, StreamWriter при AutoFlush = true записывает по одной строке дольше, чем при AutoFlush = false
     
  10. Chrome~

    Chrome~ Elder - Старейшина

    Joined:
    13 Dec 2008
    Messages:
    936
    Likes Received:
    162
    Reputations:
    27
    Все там оптимизировано и дело в буферизации. Минимальный размер буфера = 128 байт.
     
  11. Белый Ворон

    Joined:
    7 Oct 2012
    Messages:
    46
    Likes Received:
    3
    Reputations:
    0
    Тогда почему запись по 10 строк занимает в 50 раз меньше времени, чем запись по одной? Не бросается в глаза непропорциональность?
    И почему ты настаиваешь на размере буфера 4кб и 8кб, если и 128 байт вполне достаточно, при минимальных потерях данных?
     
  12. Chrome~

    Chrome~ Elder - Старейшина

    Joined:
    13 Dec 2008
    Messages:
    936
    Likes Received:
    162
    Reputations:
    27
    Если в обоих случаях используется буферизация, то время записи должно быть примерно одинаковое.
    Если говорить о производительности, то лучше чтобы размер буфера равнялся размеру кластера диска (обычно 4 или 8 кб.). Но и 128 кб. тоже неплохо, только операций вывода будет больше.