Здравствуйте, Doom100500, Вы писали:
S>>В отладчике потоки можно оттормаживать, т.е. замораживать, походил одним, поставил на паузу (freeze), походил S>>другим (freeze), разморозил пред. поток (thaw) и т.д. Можно понять, где race condition, где забыли поставить lock S>>и т.п. D>Ага, только вот этим всем начинаешь заниматься, когда уже словил ненужое переключение контекста. А когда потоки начнёшь отмораживать — не факт, что проблема воспроизведётся.
При чем здесь контекст и разделяемые данные, с возможным rc? Т.е. у потоков контекст общий, если мы не говорим
про .net'овский контекст синхронизации.
Здравствуйте, Shmj, Вы писали:
S>Встречались ли вы с идеей, что дебаггер использовать не стоит — что если рука тянется к оному — это признак грязного кода? Чистый код должен покрываться тестами и нет необходимости лезть в отладчик.
S>Каково ваше отношение к данной идее?
Если у тебя достаточно большая программа не фурычит — хрен ты её отладчиком отладишь.
Это то же самое, что картину какого-нибудь Айвазовского в замочную скважину разглядывать.
Программа должна САМА каким-то образом сказать, что в ней не в порядке.
Желательно в графическом виде.
Здравствуйте, Sharov, Вы писали:
S>Здравствуйте, Doom100500, Вы писали:
S>>>В отладчике потоки можно оттормаживать, т.е. замораживать, походил одним, поставил на паузу (freeze), походил S>>>другим (freeze), разморозил пред. поток (thaw) и т.д. Можно понять, где race condition, где забыли поставить lock S>>>и т.п. D>>Ага, только вот этим всем начинаешь заниматься, когда уже словил ненужое переключение контекста. А когда потоки начнёшь отмораживать — не факт, что проблема воспроизведётся.
S>При чем здесь контекст и разделяемые данные, с возможным rc? Т.е. у потоков контекст общий, если мы не говорим S>про .net'овский контекст синхронизации.
Я говорил о switch context, который имел место, когда многопоточность бежала на одном ядре. Тогда процессор должен сохранить и загрузить регистры. Сейчас это тоже происходит, когда потоков больше, чем ядер.
Я не корректно употребил этот термин — имел в виду состояние, когда после шага в отладчике, оказываешься в стеке (контексте) другого потока (из-за исключения, например, MyCustomTimeoutException).
А посыл был про то, что только после этого, обычно вспоминают, что можно потоки замораживать и размораживать, а это значит, что начинают отладку заново, а тут уже и проблема может не воспроизвестись, и фриз других потоков может повлиять на результат. А логи бы рассказали намного больше.
Здравствуйте, Doom100500, Вы писали:
S>>При чем здесь контекст и разделяемые данные, с возможным rc? Т.е. у потоков контекст общий, если мы не говорим S>>про .net'овский контекст синхронизации. D>Я говорил о switch context, который имел место, когда многопоточность бежала на одном ядре. Тогда процессор должен сохранить и загрузить регистры. Сейчас это тоже происходит, когда потоков больше, чем ядер.
Я это понял, но контекст актуален для процесса, у потоков он общий. Поэтому не вижу проблемы.
D>Я не корректно употребил этот термин — имел в виду состояние, когда после шага в отладчике, оказываешься в стеке (контексте) другого потока (из-за исключения, например, MyCustomTimeoutException).
И что, как это влияет на контекс процесса и на расшаренные данные? Тут ничего не должно поменяться. Речь о потоках в рамках единого
процесса. Кстати, а как такое возможно, если после исключения в активном потоке я оказался в др. потоке?
Как делал я, ловил все потоки на соотв. точке прерывания, отмараживал все и потом размаривал по одно и ходил по коду,
поочередно размораживая\замораживая другие.
D>А посыл был про то, что только после этого, обычно вспоминают, что можно потоки замораживать и размораживать, а это значит, что начинают отладку заново, а тут уже и проблема может не воспроизвестись, и фриз других потоков может повлиять на результат. А логи бы рассказали намного больше.
Я ни разу не отменяю логи. Проблем с многопоточностью из-за переключений контекста процесса у меня не было, все
в рамках одного процесса. Что-то такое может быть при отладке на уровне ядра, но я говорил про контекст .net и соотв.
управляемых потоках.
Здравствуйте, Sharov, Вы писали:
S>Здравствуйте, Doom100500, Вы писали:
S>>>При чем здесь контекст и разделяемые данные, с возможным rc? Т.е. у потоков контекст общий, если мы не говорим S>>>про .net'овский контекст синхронизации. D>>Я говорил о switch context, который имел место, когда многопоточность бежала на одном ядре. Тогда процессор должен сохранить и загрузить регистры. Сейчас это тоже происходит, когда потоков больше, чем ядер.
S>Я это понял, но контекст актуален для процесса, у потоков он общий. Поэтому не вижу проблемы.
Нет, не общий. У каждого потока свой стэк (регистр процессора), и поток мог быть прерван планировщиком между любыми не атомарными опрациями (регистры данных, MMX, SSE, etc). Это и какие-либо другие данные (нужные планировщику) и являются контекстом любого потока в системе — без разницы в одном они процессе или в разных. Переключение этого контекста происходит, если потоков больше, чем ядер, и планировщику надо давать процессорное время вытесняя другой поток. Планировщик вообще не оперирует процессами, а только потоками.
D>>Я не корректно употребил этот термин — имел в виду состояние, когда после шага в отладчике, оказываешься в стеке (контексте) другого потока (из-за исключения, например, MyCustomTimeoutException).
S>И что, как это влияет на контекс процесса и на расшаренные данные? Тут ничего не должно поменяться. Речь о потоках в рамках единого процесса.
Один поток может поменять четверть байтов в какой-то переменной типа ULONGLONG, а другой читает оттуда. Даже в рамках одного процесса эта переменная может быть на чертверь обновлена и прочитана. Это одинаково, независимо от того принадлежат ли потоки одному процессу или нет.
S>Кстати, а как такое возможно, если после исключения в активном потоке я оказался в др. потоке?
Нет, не так:
— Отлаживаем наш основной поток, в котором хотим воспроизвести проблему.
— Где-то выше по сценарию система запустила поток, который запустил операцию и ждёт её заверешения.
— Мы умные, и бесконечных ожиданий у нас нет. Вместо этого есть таймаут.
— Мы тупим в отладчике нак строкой 2990 и сморим на наши разделяемые и не разделяемые данные — изучаем их, возможно, сравниваем с какими-то эталонными или хз.
— Решаем сделать шаг и останавливаемся на исключении MyCustomTimeoutException в том потоке, который запустил операцию и ждёт её заверешения. А остановились мы там, потому что, наученные другим горьким оытом, мы выставили в отладчике опцию останавливаться на исключениях.
— Мы поняли, что тот поток, который выкинул тот самый MyCustomTimeoutException, уже успел похерить все данные, на которые мы так пристально смортрели. И начинаем отладочную сессию заново.
— Мы фризим потоки, и проблема не воспроизводится.
S>Как делал я, ловил все потоки на соотв. точке прерывания, отмараживал все и потом размаривал по одно и ходил по коду, S>поочередно размораживая\замораживая другие.
Я так тоже делал, когда логи показали где именно проблема и нужно было уже уточнить нюансы.
D>>А посыл был про то, что только после этого, обычно вспоминают, что можно потоки замораживать и размораживать, а это значит, что начинают отладку заново, а тут уже и проблема может не воспроизвестись, и фриз других потоков может повлиять на результат. А логи бы рассказали намного больше.
S>Я ни разу не отменяю логи. Проблем с многопоточностью из-за переключений контекста процесса у меня не было, все S>в рамках одного процесса. Что-то такое может быть при отладке на уровне ядра, но я говорил про контекст .net и соотв. S>управляемых потоках.
Все, даже управляемые потоки, управляются планировщиком ОС.
И я вообще не отменяю отладчик. Но он хорош, когда проблему уже отделил от основной логики и уверен, что нет никаких других стронних эффектов.
Здравствуйте, alpha21264, Вы писали:
A>Если у тебя достаточно большая программа не фурычит — хрен ты её отладчиком отладишь.
Это зависит от того, что в ней не фурычит.
Отладчик это как раз микроскоп, когда уже огородили до загончика и надо понять что там происходит на субатомнов уровне
Здравствуйте, CreatorCray, Вы писали:
CC>Это зависит от того, что в ней не фурычит. CC>Отладчик это как раз микроскоп, когда уже огородили до загончика и надо понять что там происходит на субатомнов уровне
Воот. Отладчик — это тонкий инструмент. И использовать его нужно по назначению, а не как кувалду для забивания костылей в шпалы, как в подветке про многопоточность.
Здравствуйте, alpha21264, Вы писали:
A>Если у тебя достаточно большая программа не фурычит — хрен ты её отладчиком отладишь. A>Это то же самое, что картину какого-нибудь Айвазовского в замочную скважину разглядывать.
Вот как раз ты сейчас разглядываешь картину Айвазовского в замочную скважину убогих плюсовых отладчиков. А нормальные посоны прекрасно отлаживают целый кластер из десятков разных сервисов, совмещая это в том числе и с анализом логов, и с распределенный трейсингом.
A>Программа должна САМА каким-то образом сказать, что в ней не в порядке. A>Желательно в графическом виде.
Здравствуйте, CreatorCray, Вы писали:
CC>Отладчик это как раз микроскоп, когда уже огородили до загончика и надо понять что там происходит на субатомнов уровне
Иногда отладчик и загончик тоже помогает огородить. Не будешь же ты вообще все состояние вываливать в логи, верно?
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>Вот как раз ты сейчас разглядываешь картину Айвазовского в замочную скважину убогих плюсовых отладчиков. А нормальные посоны прекрасно отлаживают целый кластер из десятков разных сервисов, совмещая это в том числе и с анализом логов, и с распределенный трейсингом.
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>Вот как раз ты сейчас разглядываешь картину Айвазовского в замочную скважину убогих плюсовых отладчиков. А нормальные посоны прекрасно отлаживают целый кластер из десятков разных сервисов, совмещая это в том числе и с анализом логов, и с распределенный трейсингом.
Это как бы разные вещи. Логгирование и трейсер позволят найти проблемный микросервис, а также правильный запрос и неправильный ответ к нему. Дальше-то что? Не все баги фиксятся методом внимательно взгляда в код, бывают сложные кодовые базы.
Здравствуйте, scf, Вы писали:
scf>Это как бы разные вещи.
Разные. В этом и прелесть использования разных механизмов параллельно. Что то в одном видно, что то в другом.
scf> Логгирование и трейсер позволят найти проблемный микросервис,
Не только. И отладчик тоже, бывает, помогает найти проблемный сервис — логи это не дамп процесса, инфа там в любом случае неполная, особенно если сервис не твой.
Я вообще не понимаю попытку некоторых в этом топике максимально сузить облать применения тех или иных инструментов. Очевидно что их надо применять строго везде, где от них есть какая то польза. А всевозможные пуристы с их неуместным максимализмом пусть идут в жопу, не?
Здравствуйте, klopodav, Вы писали:
K>Иногда можно даже не удалять, а закомментировать. Хотя на первый взгляд кажется, что этот мусор засирает код. Но оказывается — такие закомментированные fprintf'ы тоже могут быть полезны как дополнение к другим комментариям. Они показывают, на что следует обратить особое внимание. И на случай, если в будущем в поведении этого кода обнаружится неведомая хрень — будет примерно понятно, что снова надо вывести в лог, чтобы эту хрень отловить.
Это называется логгирование, строчки с логгированием не комментируюся, а отключаются, на уровне компиляции или в рантайме. см. "уровни логгирования"
Здравствуйте, Ночной Смотрящий, Вы писали:
НС>А всевозможные пуристы с их неуместным максимализмом пусть идут в жопу, не?
Вот сам туда и иди.
Если над бракоделами не стоять с воот такой вот дубиной, то не успеешь оглянуться, как система с нормальным дизайном и адекатным покрытием юнит-тестами превращается в копромонолит с полутора хромыми тестами (остальные отключили, потому что они "падают").
Здравствуйте, landerhigh, Вы писали:
L>Если над бракоделами не стоять с воот такой вот дубиной, то не успеешь оглянуться, как система с нормальным дизайном и адекатным покрытием юнит-тестами превращается в копромонолит с полутора хромыми тестами (остальные отключили, потому что они "падают").
Здравствуйте, Ночной Смотрящий, Вы писали:
L>>Если над бракоделами не стоять с воот такой вот дубиной, то не успеешь оглянуться, как система с нормальным дизайном и адекатным покрытием юнит-тестами превращается в копромонолит с полутора хромыми тестами (остальные отключили, потому что они "падают"). НС>И при чем тут отладчик?
Да потому вот так и норовят "небольшое изменение", для которого нужно бы написать отдельный юнит тест или исправить существующий, "по-быстренькому" "прогоняют под отладчиком".
Если вот тут сразу по рукам как следует не дать, через несколько недель будет поздно.
Здравствуйте, landerhigh, Вы писали:
НС>>И при чем тут отладчик? L>Да потому вот так и норовят "небольшое изменение", для которого нужно бы написать отдельный юнит тест или исправить существующий, "по-быстренькому" "прогоняют под отладчиком".
Ни разу с таким не сталкивался и не очень понимаю как такое возможно. Решение о написании теста на тот или иной кейс никак не зависит от наличия отладчика.
Здравствуйте, Ночной Смотрящий, Вы писали:
L>>Да потому вот так и норовят "небольшое изменение", для которого нужно бы написать отдельный юнит тест или исправить существующий, "по-быстренькому" "прогоняют под отладчиком". НС>Ни разу с таким не сталкивался и не очень понимаю как такое возможно. Решение о написании теста на тот или иной кейс никак не зависит от наличия отладчика.
Здравствуйте, Doom100500, Вы писали:
S>>И что, как это влияет на контекс процесса и на расшаренные данные? Тут ничего не должно поменяться. Речь о потоках в рамках единого процесса. D>Один поток может поменять четверть байтов в какой-то переменной типа ULONGLONG, а другой читает оттуда. Даже в рамках одного процесса эта переменная может быть на чертверь обновлена и прочитана. Это одинаково, независимо от того принадлежат ли потоки одному процессу или нет.
Все так, если операция не атомарна (чтение\запись адреса в памяти или CAS какой-нибудь). Но можно ставить bp в соотв.
место, а лучше до и отлавливать и тормозить другие потоки. В отладке не проблеме это избежать, надо только аккуратно
ходить отлаживаемым потоком и следить, чтобы не перекинуло на другой. Я отлавливал все левые потоки на br и замораживал.
S>>Кстати, а как такое возможно, если после исключения в активном потоке я оказался в др. потоке? D>Нет, не так: D>- Отлаживаем наш основной поток, в котором хотим воспроизвести проблему. D>- Где-то выше по сценарию система запустила поток, который запустил операцию и ждёт её заверешения. D>- Мы умные, и бесконечных ожиданий у нас нет. Вместо этого есть таймаут. D>- Мы тупим в отладчике нак строкой 2990 и сморим на наши разделяемые и не разделяемые данные — изучаем их, возможно, сравниваем с какими-то эталонными или хз. D>- Решаем сделать шаг и останавливаемся на исключении MyCustomTimeoutException в том потоке, который запустил операцию и ждёт её заверешения. А остановились мы там, потому что, наученные другим горьким оытом, мы выставили в отладчике опцию останавливаться на исключениях. D>- Мы поняли, что тот поток, который выкинул тот самый MyCustomTimeoutException, уже успел похерить все данные, на которые мы так пристально смортрели. И начинаем отладочную сессию заново. D>- Мы фризим потоки, и проблема не воспроизводится.
Понял о чем речь. Выше я это отметил -- можно ставить bp в callback'е. А можно просто аккуратно ходить своим потоком и не долбить F9-F10,
и внимательно следить какой поток активный, чтобы потом переключиться на нужный. Т.е. поток по таймауту надо отловить до того, как он
упадет с MyCustomTimeoutException. Ну либо вручную под отладчиком увеличить таймаут или вообще -1 сделать.