У меня есть программа, которая загружает файл (где угодно от 10 МБ до 5 ГБ), блок за один раз (ReadFile), и для каждого блока работает, ряд математических операций (в основном вычисляет хеш).
После вычисления хеша это хранит информацию о блоке в карте STL (в основном <chunkID, hash>
) и затем пишет сам блок в другой файл (WriteFile).
Это - все, что это делает. Эта программа заставит определенные ПК дросселировать и переставать работать. Мышь начинает заикаться, диспетчер задач берет>, 2 минуты для показа ctrl+alt+del безразличен, запускающие программы являются медленными.... работы.
Я сделал буквально все, о чем я могу думать для оптимизации программы и трижды проверил все объекты.
Что я сделал:
Даже, в конце концов, это, приложение все еще приводит к в масштабе всей системы, зависают на определенных машинах при определенных обстоятельствах.
Perfmon и Process Explorer показывают минимальное использование ЦП (со сном), никакие постоянные чтения/записи от диска, немного трудных отсутствий страницы (и только ~30k отсутствия страницы во время жизни приложения на входном файле на 5 ГБ), мало виртуальной памяти (никогда, чем 150 МБ), никакие пропущенные дескрипторы, никакие утечки памяти.
Машины я протестировал его на выполненном Windows XP - включенные версии Windows 7, x86 и x64. Ни один не имеет меньше чем 2 ГБ RAM, хотя проблема всегда усиливается при более низких условиях памяти.
Я в замешательстве относительно того, что сделать затем. Я не знаю то, что вызывает его - я порван между ЦП или Памятью как преступник. ЦП, потому что безо сна и под различными приоритетами потока производительности системы изменяется заметно. Память, потому что существует огромная разница в том, как часто проблема происходит при использовании unordered_set по сравнению с dense_hash_map Google.
Что является действительно странным? Очевидно, дизайн ядра NT, как предполагается, предотвращает этот вид поведения от когда-либо появления (приложение непривилегированного режима, управляющее системой к этому виду экстремальной низкой производительности!?)....., но когда я компилирую код и выполняю его на OS X или Linux (это - довольно стандартный C++ повсюду) это работает превосходно даже на плохих машинах с небольшой RAM и более слабыми центральными процессорами.
Что я, как предполагается, делаю затем? Как я знаю то чем, черт возьми, случается так, что Windows делает негласно, это уничтожает производительность системы, когда все индикаторы - то, что само приложение ничего не делает экстремальное значение?
Любой совет приветствовался бы.
Оказывается, это ошибка компилятора Visual Studio. Использование другого компилятора полностью решает проблему.
В моем случае я установил и использовал компилятор Intel C ++, и даже при отключенной оптимизации я не заметил полного зависания системы, которое у меня было с компиляторами Visual Studio 2005 - 2010 в этой библиотеке.
Я не уверен, что заставляет компилятор генерировать такой неработающий код, но похоже, что мы купим копию компилятора Intel.
Некоторые вещи для проверки:
РЕДАКТИРОВАТЬ
Еще идеи. Возможно, ваша программа слишком сильно удерживает блокировку GDI. Это объяснило бы, что все остальное работает медленно без высокой загрузки ЦП. Только одно приложение одновременно может иметь блокировку GDI. Это приложение с графическим интерфейсом или просто консольное приложение?
Вы также упомянули RtlEnterCriticalSection.Это дорогостоящая операция, и она может довольно легко повесить систему, т. Е. Несовпадение входов и выходов. Вы вообще многопоточны? Причина замедления в гонке между потоками?
XPerf - ваш проводник. Посмотрите видео PDC об этом, а затем найдите некорректно работающее приложение. Он точно скажет вам, что происходит во всей системе, он чрезвычайно мощный.
Мне нравятся предложения по кэшированию / перегрузке диска, но если это не так, то вот несколько предложений scattershot:
На какие не-MSVC библиотеки, если таковые имеются, вы ссылаетесь?
Можно ли изменить вашу программу (# ifdef'd) работать без графического интерфейса? Возникла ли проблема?
Вы добавили :: Sleep (100) после каждого цикла в каждом потоке, верно? О скольких потоках вы говорите? Горстка или сотни? Сколько примерно времени занимает каждая петля? Что произойдет, если вы сделаете это :: Sleep (10000)?
Возможно, ваша программа делает что-то еще, что блокирует ограниченные ресурсы (ProcExp может показать вам, какие дескрипторы собираются ... конечно, у вас могут быть проблемы с ProcExp, а не ответ: - [)
Вы уверены, что CriticalSections предназначены только для пользователя? Я вспоминаю, что это было так, когда я работал над Windows (или мне так казалось), но Microsoft могла это изменить. Я не вижу никаких гарантий в статье MSDN Critical Section Objects ( http://msdn.microsoft.com/en-us/library/ms682530%28VS.85%29.aspx ) ... и это заставляет меня задуматься: Антиконвойные блокировки в Windows Server 2003 SP1 и Windows Vista
Хммм ... по-видимому, сейчас мы все многопроцессорные, так что вы устанавливаете счетчик оборотов на CS?
Как насчет запуска отладочной версии одной из этих ОС и мониторинга вывода отладки ядра (с помощью DbgView) ... возможно, используя отладчик ядра из Platform SDK ... если MS все еще вызывает его это?
Интересно, может ли VMMap (еще одна служебная программа SysInternal / MS) помочь с гипотезой о кэшировании диска.
Похоже, вы пытаетесь что-то исправить, не зная, в чем проблема. Делайте стекшоты. Они сообщат вам, что делает ваша программа при возникновении проблемы. Получить снимки стека может быть непросто, если проблема возникает на других машинах, на которых нельзя использовать IDE или сэмплер стека. Одна из возможностей - убить приложение и получить дамп стека, когда оно срабатывает. Вам нужно воспроизвести проблему в среде, где вы можете получить дамп стека.
Добавлено: вы говорите, что он хорошо работает в OSX и Linux и плохо работает в Windows. Я предполагаю, что отношение времени выполнения - довольно большое число, например, 10 или 100, если у вас даже хватило терпения дождаться этого. Я сказал это в комментарии, но это ключевой момент. Программа чего-то ждет, а вам нужно узнать что. Это может быть что угодно из упомянутого людьми, но это не случайно .
Каждая программа, все время, пока она выполняется, имеет стек вызовов, состоящий из иерархии инструкций вызова по определенным адресам. Если в какой-то момент выполняется вычисление, последняя инструкция в стеке не вызывается. Если он находится в режиме ввода-вывода, стек может достигать нескольких уровней библиотечных вызовов, которые вы не можете увидеть. Это нормально. Каждая инструкция вызова в стеке ожидает. Он ожидает завершения запрошенной работы. Если вы посмотрите на стек вызовов и посмотрите, где находятся инструкции вызова в вашем коде , вы узнаете, чего ждет ваша программа.
Ваша программа, поскольку она занимает так долго , тратит почти все своего времени на ожидание завершения, и, как я уже сказал, это то, что вам нужно выяснить. Получите дамп стека, пока он работает медленно, и он даст вам ответ. Вероятность того, что он его пропустит, составляет 1 / отношение медленности.
Извините за такую элементарность, , но многие люди ( и создатели профилировщиков ) не понимают . Они думают, что нужно измерить.
Я знаю, что вы сказали, что отслеживали использование памяти, и что здесь оно кажется минимальным, но симптомы очень похожи на сумасшедшую работу ОС, что определенно вызывают общую потерю отзывчивости ОС, как вы видите.
Когда вы запускаете приложение в файле, скажем, от 1/4 до 1/2 размера доступной физической памяти, работает ли оно лучше?
Я подозреваю, что может происходить то, что Windows "помогает" кэшировать ваш диск читает в память и не передает эту кеш-память вашему приложению для использования, вынуждая ее перейти на свопинг. Таким образом, даже несмотря на то, что использование свопа минимально (150 МБ), оно постоянно входит и выключается по мере вычисления хэша. Это ставит систему на колени.