Проблемы тестирования 64 битных приложений


Содержание

«Изменения в 64-разрядных приложениях не разрешены» при отладке в Visual Studio 2008

Я использую Visual Studio 2008, С#. Я пытаюсь использовать edit-and-continue (редактировать код при отладке) и получить это исключение:

«Изменения в 64-битных приложениях не разрешены»

Почему? Есть ли способ обхода?

«Редактировать и продолжать» не поддерживается в 64-разрядных приложениях на уровне CLR, поэтому Visual Studio не может его реализовать.

Самый простой способ обойти эту проблему — нацелить ваше приложение на чипы x86. Это заставит его работать в режиме Wow64 как 32-битный процесс и, следовательно, иметь возможность ENC. Вы можете сделать это, выполнив следующие

  • Щелкните правой кнопкой мыши на приложении .EXE и выберите «Свойства»
  • Перейдите на вкладку «Построение».
  • Измените поле со списком платформы Target на x86

Лично, что я действительно хочу, это остановить и отредактировать, а не редактировать и продолжить.

Поэтому я просто отключу Инструменты/Параметры/Отладка/Редактирование и Продолжить.

Выполнение этого запрета на то, что надоедливое диалоговое окно от приставания ко мне о недостающей функции, которой я не хотел в первую очередь: -)

Как и jcopenha, пока нет изменений и продолжений на x64. Текущая версия 64-битной CLR ее не поддерживает. Тем не менее, там есть работа.

Вам нужно скомпилировать вашу управляемую сборку с целевым процессором x86. Это приведет к использованию 32-битной CLR, а не 64-битной CLR.

Для проекта VB щелкните правой кнопкой мыши по проекту и перейдите в раздел «Свойства/Компилировать/Расширенные параметры компиляции/Целевой ЦП» и установите его в «x86». Для проекта С# щелкните правой кнопкой мыши по проекту и перейдите на страницу «Сооружения/сборки/платформы» и установите его на «x86».

Разработка ресурсоемких приложений в среде Visual C++

Аннотация.

Статья познакомит разработчиков прикладного программного обеспечения с задачами, которые ставит перед ним массовое внедрение многоядерных 64-битных вычислительных систем, знаменующих революционное увеличение вычислительной мощности, доступное рядовому пользователю. Будут рассмотрены вопросы эффективного использования аппаратных ресурсов для решения повседневных прикладных задач в рамках операционной системы Windows x64.

Информация читателю.

По умолчанию в статье под операционной системой будет пониматься Windows. Под 64-битными системами следует понимать архитектуру x86-64 (AMD64). Под средой разработки — Visual Studio 2005/2008 . Скачать демонстрационный пример, о котором будет говориться в статье можно по адресу: http://www.Viva64.com/articles/testspeedexp.zip .

Введение.

Параллельные вычисления и большой объем оперативной памяти перестают быть привилегией больших программно-аппаратных комплексов, предназначенных для масштабных научных вычислений, и переходят на службу в решении повседневных задач, связанных с работой, учебой, развлечениями и компьютерными играми.

Возможность распараллеливания и большой объем оперативной памяти с одной стороны облегчает разработку ресурсоемких приложений, но с другой требует от программиста большей квалификации и знаний в области параллельного программирования. К сожалению, сейчас этой квалификацией и знаниями обладают далеко не все разработчики. Но не потому, что они плохие разработчики, а лишь в силу того, что им не приходилось сталкиваться с подобными задачами. Это не удивительно, так как созданием параллельных систем обработки информации до не недавнего времени занимались в основном в научных институтах, решая задачи моделирования и прогнозирования. Параллельные вычислительные комплексы с большим объемом памяти применялись и в прикладных целях на предприятиях, в банках и так далее, но до недавнего времени они были весьма дороги и не многие разработчики имели возможность познакомиться с особенностями разработки программного обеспечения для таких систем.

Авторам статьи довелось участвовать в разработке ресурсоемких программных продуктов связанных с визуализацией и моделированием физических процессов и на себе почувствовать всю специфичность разработки, тестирования и отладки систем подобного типа. Под ресурсоемким программным обеспечением понимается программный код, эффективно использующий возможности многопроцессорных систем и большой объем памяти (от гигабайта и более). Поэтому, хочется по возможности снабдить разработчиков знаниями, которые могут пригодиться им в ближайшее время при освоении современных параллельных 64-битных систем.

Справедливо отметим, что вопросы связанные, с параллельным программированием уже давно и подробно проработаны и нашли свое отражение во многих книгах, статьях и учебных курсах. В связи с этим акцент в статье будет смещен в сторону организационных и практических вопросов разработки высокопроизводительных приложений и использованию 64-битных технологий.

Говоря о 64-битных системах, мы будем считать, что они используют модель данных LLP64 (см. таблицу N1). Именно такая модель данных используется в 64-битных версиях операционной системы Windows. Но приведенная информация может быть полезной и при работе с системами с отличной от LLP64 моделью данных.

1. Смело используйте параллельность и 64-битность.

Осознавая всю консервативность в разработке больших программных систем, тем не менее, хочется порекомендовать использовать те возможности, которые представляют многоядерные 64-битные процессоры. Это может стать большим конкурентным преимуществом перед аналогичными системами, а так же стать хорошим новостным поводом в рекламных компаниях.

Нет смысла откладывать 64-битность и параллельность на потом, так как их освоение неизбежно. Можно безболезненно пропустить повсеместное увлечение новым языком программирования или не оптимизировать программу под технологию MMX. Но нельзя уйти от роста объема обрабатываемых данных и замедления скорости роста тактовой частоты. Давайте остановимся на этом утверждении более подробно.

Параллелизм становится основой роста производительности, что связано с замедлением темпов роста тактовой частоты современных микропроцессоров. В то время как количество транзисторов на кристалле неуклонно растет, с 2005 года наметился резкий спад темпов роста тактовой частоты (смотри рисунок 1). Интересной работой по этой теме является статья «The Free Lunch Is Over. A Fundamental Turn Toward Concurrency in Software».

В последние 30 лет производительность определялась тактовой частотой, оптимизацией исполнения команд и увеличением кэша. В ближайшие годы она будет определяться многоядерностью. Основным направлением развития технологий программирования станет развитие средств параллельного программирования.

Параллельное программирование позволит не только обойти проблему замедления скорости роста тактовой частоты, но и принципиально перейти к созданию масштабируемого программного обеспечения, полностью использующего увеличение количества вычислительных узлов в процессоре. То есть, программное обеспечение будет получать прирост производительности не только от увеличения тактовой частоты микропроцессора, но и от роста количества ядер. За такими системами будущее программного обеспечения. И тот, кто быстрее освоит новые технологи, сможет существенно перераспределить рынок программного обеспечения в свою пользу.

Использование 64-битных технологий, хотя и не выглядит столь внушительно по сравнению с параллельностью, тем не менее, также открывает много новых возможностей. Во-первых, это бесплатный прирост производительности на 5-15%. Во-вторых, большое адресное пространство решает проблему фрагментации оперативной памяти при работе с большими объектами. Решение этой задачи является головной болью для многих разработчиков, чьи программы аварийно завершаются из-за нехватки памяти после нескольких часов работы. В-третьих, это возможность легко работать с массивами данных в несколько гигабайт. Иногда это приводит к поразительному приросту производительности, за счет исключения операций доступа к жесткому диску.

Если вышесказанное не убедило Вас в преимуществах 64-битных систем, то посмотрите внимательнее, чем занимаются Ваши коллеги или Вы сами. Кто-то оптимизирует код, повышая производительность функции на 10%, хотя эти 10% можно получить простой перекомпиляцией программы под 64-битную архитектуру? Кто-то создает свой класс для работы с массивами, подгружаемые из файлов, так как полностью этот массивы не помещается в память? Вы делаете свой менеджер распределения памяти, чтобы не фрагментировать память? Если Вы ответите на один из вопросов — «Да», то следует остановиться и подумать. Вероятно, Вы ведете бесполезное сражение. И возможно будет выгоднее потратить время на перенос вашего приложения на 64-битную систему, где все эти вопросы исчезнут сами собой. Тем более что рано или поздно, Вы все равно потратите на это время.

Подытожим сказанное. Нет смысла тратить время, чтобы выжать последние возможности из 32-битной архитектуры. Экономьте свое время. Используйте для повышения производительности параллельность и 64-битное адресное пространство. Сделайте новый информационный повод и опередите своих конкурентов при освоении рынка высокопроизводительных приложений.

2. Вооружитесь хорошим аппаратным обеспечением.

Итак, Вы приняли решение использовать параллельность и 64-битные технологии в ваших программных разработках. Замечательно. Тогда давайте вначале рассмотрим некоторые организационные вопросы.

Не смотря на то, что Вам приходится сталкиваться с разработкой сложных программ, обрабатывающих огромные объемы данных, руководство все равно часто не понимает необходимость обеспечения своих разработчиков наиболее мощными компьютерами. Хотя Ваши приложения могут быть предназначены для мощных рабочих станций, Вам, возможно, все равно придется их тестировать и отлаживать на своей рабочей машине. Конечно, потребность в мощной вычислительной технике существует у всех программистов, пусть даже их программы не обрабатывают гигабайты данных. Всем приходится их компилировать, запускать вспомогательные тяжеловесные инструменты и так далее. Но только разработчик ресурсоемкого программного обеспечения может во всех деталях ощутить неприятности от недостаточного количества оперативной памяти или медлительности дисковой подсистемы.

Покажите эту часть статьи своему руководителю. Сейчас мы попробуем объяснить, почему выгодно вложить средства в Ваши инструменты — компьютеры.

Это может прозвучать неоригинально, но быстрый процессор и быстрая дисковая подсистема могут существенно ускорить процесс компиляции приложений! Кажется между двумя или одной минутой компиляции части кода нет разницы? Она огромна! Минуты выливаются в часы, дни, месяцы. Попросите своих программистов посчитать, сколько времени они проводят в ожидании компиляции кода. Поделите это время хотя бы в 1.5 раза и затем сможете подсчитать, как быстро окупится вложение в новую технику. Уверяю Вас — Вы будете приятно удивлены.

Помните и про следующий эффект, который будет экономить рабочее время. Если какое-то действие длится 5 минут, то человек подождет. Если 10 — то он пойдет готовить кофе, читать форумы или играть в пинг-понг, что займет гораздо больше 10 минут! И, не потому что он злодей, или очень хочет кофе — ему будет просто скучно. Не давайте прерываться действию: нажал — получил результат. Сделайте так, чтобы те процессы, которые занимали 10 минут — начали занимать меньше 5.

Еще раз хочу обратить внимание — цель не занять свободное время программиста полезным делом, а убыстрить процессы в целом. Установка второго компьютера (двухпроцессорной системы) с целью, чтобы программист переключался в минуты ожидания на другие задачи — в корне ошибочна. Труд программиста, это не труд дворника, где в перекурах между колкой льда можно почистить лавку от снега. Труд программиста требует концентрации над задачей и удержание в памяти множества ее элементов. Не старайтесь переключить программиста, старайтесь сделать так, чтобы он как можно быстрее мог продолжить решать задачу, над которой сейчас работает. Никакой пользы от такой попытки не будет, Вы только еще больше утомите разработчика, при меньшей эффективности труда. Согласно статье «Стрессы многозадачной работы: как с ними бороться» [2] необходимое время на погружение в другую или прерванную задачу составляет 25 минут. Если не обеспечить неприрывность процесса, половина времени будет уходить на это самое переключение. Не важно, что это — игра в пинг-понг, или поиск ошибки в другой программе.

Не жалейте купить несколько лишних гигабайт памяти. Эта покупка окупится после нескольких этапов отладки программы, выделяющей большой объем памяти. Знайте, что недостаток оперативной памяти приводит к выгрузке данных на диск (swapping) и может замедлить процесс отладки с минут до часов.

Не жалейте снабдить машину RAID подсистемой. Не будем теоретиками, вот пример из личной практики (таблица N2).

Конфигурация (обратите внимание на RAID) Время сборки среднего проекта, использующего большое количество внешних библиотек.
AMD Athlon(tm) 64 X2 Dual Core Processor 3800+, 2 GB of RAM,2 x 250Gb HDD SATA — RAID 0 95 минут
AMD Athlon(tm) 64 X2 Dual Core Processor 4000+, 4 GB of RAM,500 Gb HDD SATA (No RAID) 140 минут
Таблица 2. Пример влияние RAID на скорость сборки приложения.

Уважаемые руководители! Поверьте, что экономия на вычислительной технике с лихвой окупается простоями в работе программистов. Такие компании как Microsoft обеспечивают разработчиков последними моделями вычислительно техники, не от щедрости и расточительности. Они как раз хорошо умеют считать деньги и их пример не следует игнорировать.

На этом текст, посвященный руководителям, закончен, и мы вновь хотим обратиться к создателям программных решений. Требуйте, требуйте для себя той техники, которую считаете себе необходимой. Не стесняйтесь, в конце концов Ваш начальник, скорее всего, может просто не понимать, что это выгодно всем. Нужно заниматься просветительской работой. Тем более в случае отставания в планах, виновным будете казаться Вы. Проще выбить новую технику, чем пытаться объяснить, на что Вы тратите время. Сами представьте, как может звучать Ваше оправдание о правке одной единственной ошибки в течение всего дня: «Так ведь проект большой прислали. Я запустил под отладчиком, долго ждал. А памяти у меня только 1 гигабайт. А больше ничем параллельно заниматься невозможно. Windows в своп ушел. Нашел ошибку поправил, но так ведь опять снова запустить и проверить нужно. «. Ваш начальник возможно промолчит, но будет считать Вас просто лентяем. Не доводите до этого.

Ваша первоочередная задача при разработке ресурсоемкого приложения — это не проектирование будущей системы и даже не изучение теории, а заблаговременное требование о закупке всего необходимого аппаратного и программного обеспечения. Только после того можно смело и эффективно приступать к созданию ресурсоемких программных решений. Невозможно писать и проверять параллельные программы, без многоядерных процессоров. И невозможно писать систему для обработки больших объемов данных без необходимого объема оперативной памяти.

Прежде чем перейти к следующей теме, хочется поделиться еще некоторыми мыслями, которые помогут сделать работу более комфортной.


Проблему медленной сборки проекта можно попробовать решить путем использования специальных средств параллельной сборки подобной, например системе IncrediBuild by Xoreax Software (http://www.xoreax.com). Естественно существуют и другие подобные системы, которые можно поискать в сети.

Проблему тестирования приложений на огромных массивах данных (запуск пакетов с тестами), для которых рабочие машины недостаточно производительны, можно решить использованием нескольких специальных мощных машин с удаленным доступом. Примером удаленного доступа может служить Remote Desktop или X-Win. Обычно одновременно тестовые запуски осуществляет только малое количество разработчиков. И для коллектива из 5-7 человек вполне может хватить 2-х мощных выделенных машин. Это будет не самое удобное решение, но весьма экономичное, по сравнению с приобретением таких рабочих станций каждому разработчику.

3. Меняем отладчик на систему логирования.

Следующим препятствием, которое станет на Вашем пути, в разработке систем для обработки большого объема данных, будет то, что Вам, скорее всего, придется пересмотреть свою методологию работы с отладчиком или даже полностью отказаться от его использования.

Ряд специалистов предлагает отказаться от этой методологии тестирования по идеологическим соображениям. Основной аргумент состоит в том, что отладчик провоцирует использование метода проб и ошибок. Человек видя некорректное поведение алгоритма, на каком то, из этапов его выполнения тут же производит правки, не вникая в суть, почему эта ошибка была допущена и не задумывается над способом ее исправления. Если он не угадал с исправлением, то при следующем выполнении кода, он это заметит и внесет новые правки. Результатом становится менее качественный код. Причем автор этого кода далеко не всегда уверен, что понимает, как он работает. Противники отладки предлагают заменять ее более строгой дисциплиной разработки алгоритмов, использованием как можно более мелких функций, чтобы принципы их работы были очевидны. Также они предлагают уделять большее внимание юнит-тестированию и использовать системы логирования для анализа корректности работы программы.

В описанной критике систем отладки есть рациональные зерна, но, как и во многих других случаях следует все взвесить и не впадать в крайности. Использование отладчика часто удобно и может сэкономить много сил и времени.

3.1. Причины, снижающие привлекательность отладчика.

Плохая применимость отладчиков при работе с системами, обрабатывающими большие объемы данных, связана, к сожалению, не с идеологическими, а практическими сложностями. Хочется познакомить читателей с этими сложностями, чтобы сэкономить их время на борьбу с инструментом-отладчиком, когда он уже малопригоден и подвигнуть их к поиску альтернативных решений.

Рассмотрим причины, требующие использования альтернативных средств вместо классического отладчика (например, встроенного в среду Visual C++ ).

1) Медленное выполнение программы.

Выполнение программ под отладчиком, обрабатывающей миллионы или миллиарды элементов может стать практически неосуществимым из-за временных затрат. Во-первых, необходимо использовать отладочный вариант кода с выключенной оптимизацией, что уже существенно замедляет скорость работы алгоритма. Во-вторых, в отладочном варианте происходит выделение большего объема памяти для контроля выхода за пределы массивов, заполнение памяти при выделении/удалении и так далее, что еще более замедляет время работы программы.

Можно резонно заметить, что отлаживать программу вовсе не обязательно на больших рабочих объемах данных, а обойтись тестовыми задачами. К сожалению, это не так. Неприятный сюрприз заключается в том, что при разработке 64-битных систем, Вы не можете быть уверены в корректности работы алгоритмов, тестируя их на небольших объемах данных, а не на рабочих объемах размером в гигабайты.

Приведем один простой пример, демонстрирующий проблему необходимости тестирования на большом объеме данных.

Данная программа читает файл и сохраняет в массиве все символы, относящиеся к заглавным английским буквам. Если все символы в выходном файле будут заглавными английскими буквами, то на 32-битной системе мы не сможем поместить в массив более 2*1024*1024*1024 символов, а следовательно и обработать файл более 2 гигабайт. Представим, что такая программа корректно использовалась на 32-битной системе, с учетом этого ограничения и никаких ошибок не возникало.

На 64-битной системе возникнет желание обрабатывать файлы большего размера, так как снимается ограничение на размер массива в 2 гигабайта. К сожалению, программа написана некорректно с точки зрения модели данных LLP64 (см. таблицу N1), используемой в 64-битной операционной системе Windows. В цикле используется переменная типа int, размер которой по-прежнему составляет 32 бита. В случае если размер файла будет равен 6 гигабайт, то условие «i != fileSize» никогда не будет выполнено и возникнет вечный цикл.

Данный код приведен, чтобы продемонстрировать сложность поиска с помощью отладчика ошибок, которые возникают только на большом объеме памяти. Получив зацикливание при обработке файла в 64-битной системе можно взять для обработки файл размером в 50 байт и просмотреть работу функции под отладчиком. Но ошибка на таком объеме данных не возникнет, а смотреть в отладчике обработку 6 миллиардов элементов невозможно.

Естественно следует понимать, что это всего лишь пример, и что его легко можно отладить и понять причину зацикливания. В сложных системах, к сожалению, такое часто становится практически нереализуемым из-за медленности обработки большого объема данных.

Более подробно с подобными неприятными примерами Вы можете познакомиться в статье «Забытые проблемы разработки 64-битных программ» и » 20 ловушек переноса Си++ — кода на 64-битную платформу».

Использование нескольких параллельно выполняемых потоков команд для ускорения обработки большого объема данных давно и успешно используется в кластерных системах и высокопроизводительных серверах. Но только с приходом на массовый рынок многоядерных микропроцессоров, возможность параллельной обработки данных начинает широко использоваться прикладным программным обеспечением. И актуальность разработки параллельных систем со временем будет только расти.

К сожалению, не просто объяснить, в чем состоит сложность отладки параллельных программ. Только столкнувшись с задачей поиска и исправления ошибок в параллельных системах можно почувствовать и понять беспомощность инструмента под названием отладчик. Но в целом проблемы можно свести к невозможности воспроизведения многих ошибок и влиянию процесса отладки на последовательность работы параллельных алгоритмов.

Более подробно с вопросами отладки параллельных систем Вы можете познакомиться в следующих статьях: » Технология отладки программ для машин с массовым параллелизмом», «Multi-threaded Debugging Techniques», «Detecting Potential Deadlocks».

Перечисленные трудности решаются использованием специализированных методологий и инструментов. С некорректным 64-битным кодом можно бороться, используя статические анализаторы, работающие с исходным кодом программы и не требующим его запуска. Примером может служить статический анализатор Viva64 .

Для отладки параллельных систем следует обратить внимание в сторону таких инструментов как TotalView Debugger (TVD). TotalView это отладчик для языков Си, Си++ и фортран, который работает на Юникс-совместимых ОС и Mac OS X. Он позволяет контролировать нити исполения (потоки, thread), показывать данные одного или всех потоков, может синхронизировать нити через точки останова. Он поддерживает также параллельные программы, использующие MPI и OpenMP.

Другим интересными приложениями является средства анализа многопоточности Intel® Threading Analysis Tools.

3.2. Использование системы логирования.

Перечисленные и оставшиеся за кадром инструменты, безусловно, полезны и могут стать хорошим подспорьем при разработке высокопроизводительных приложений. Но не стоит забывать и о такой проверенной временем методологии, как использование систем логирования. Отладка методом логирования за несколько десятилетий ничуть не утратила актуальности и остается верным средством, о котором мы поговорим более подробно. Единственное изменение, которое накладывает время на системы логирования, это возросшие к ним требования. Попробуем перечислить свойства, которыми должна обладать современная система логирования, для высокопроизводительных систем:

  • Код, обеспечивающий логирование данных в отладочной версии, должен отсутствовать в конечной версии программного продукта. Во-первых, это связано с увеличением быстродействия и уменьшением размера программного продукта. Во-вторых, не позволяет использовать отладочную информацию для взлома приложения или иных несанкционированных действий.
  • Интерфейсы системы логирования должна быть лаконичны, чтобы не загромождать основной код программы.
  • Сохранение данных должно осуществляться как можно быстрее, чтобы вносить минимальное изменение во временные характеристики параллельных алгоритмов.
  • Полученный лог должен быть наглядным и легко поддаваться анализу. Должна существовать возможность разделить информацию, полученную от различных потоков, а также варьировать ее уровень подробности.

Система логирования, отвечающая таким качествам позволяет универсально решать как задачу отладки параллельных алгоритмов, так и отлаживать алгоритмы обрабатывающие огромные массивы данных.

В статье не будет приведен конкретный код системы логирования. Такую систему трудно сделать универсальной, так как она сильно зависит от среды разработки, особенностей проекта, предпочтений разработчика и многого другого. Вместо этого будет рассмотрен ряд технических решений, которые помогут Вам создать удобную и эффективную систему логирования, если в том возникнет необходимость.

Самым простым способом осуществить логирование является использование функции аналогичной printf, как показано в примере:

Естественным недостатком является то, что информация будет выводиться как в отладочном режиме, так и в конечном продукте. Поэтому, следует модернизировать код следующим образом:

Это уже лучше. Причем обратите внимание, что мы используем для выбора реализации функции WriteLog не стандартный макрос _DEBUG, а собственный макрос DEBUG_MODE. Это позволяет включать отладочную информацию в Release-версии, что важно при отладке на большом объеме данных.

К сожалению, теперь при компиляции не отладочной версии в среде Visual C++ возникает предупреждение: «warning C4002: too many actual parameters for macro ‘WriteLog'». Можно отключить это предупреждение, но это является плохим стилем. Можно переписать код, как показано ниже:

Приведенный код не является элегантным, так как приходится использовать двойные пары скобок, что часто забывается. Поэтому внесем новое усовершенствование:

Этот код выглядит сложным, но он позволяет писать одинарные скобки. При выключенном DEBUG_MODE этот код превращается в ничто, и его можно смело использовать в критических участках кода.

Следующим усовершенствованием может стать добавление к функции логирования таких параметров как уровня детализации и типа выводимой информации. Уровень детализации можно задать как параметр, например:

Этот способ удобен тем, что решение, отфильтровать или не отфильтровать маловажные сообщения можно принять уже после завершения работы программы, используя специальную утилиту. Недостаток такого метода в том, что всегда происходит вывод всей информации, как важной, так и второстепенной, что может снижать производительность. Поэтому можно создать несколько функций вида WriteLogMain, WriteLogFull и так далее, реализация которых будет зависеть от режима сборки программы.

Мы упоминали о том, что запись отладочной информации должна как можно меньше влиять на скорость работы алгоритма. Этого можно достичь, создав систему накопления сообщений, запись которых происходит в параллельно выполняемом потоке. Схематично этот механизм представлен на рисунке N2.

Как можно видеть на рисунке, запись очередной порции данных происходит в промежуточный массив строк фиксированной длины. Фиксированный размер массива и строк в нем позволяет исключить дорогостоящие операции выделения памяти. Это нисколько не снижает возможности такой системы. Достаточно выбрать длину строк и размер массива с запасом. Например, 5000 строк длиной в 4000 символов будет достаточно для отладки практически любой системы. А объем памяти в 20 мегабайт необходимый для этого, согласитесь, не критичен для современных систем. Если же массив все равно будет переполнен, то несложно предусмотреть механизм досрочной записи информации в файл.

Приведенный механизм обеспечивает практически моментальное выполнение функции WriteLog. Если в системе присутствуют ненагруженные процессорные ядра, то и запись в файл будет практически прозрачна для основного кода программы.

Преимущество описываемой системы в том, что она практически без изменений способна функционировать при отладке параллельной программы, когда в лог пишут сразу несколько потоков. Следует только добавить сохранение идентификатора процесса, чтобы потом можно было узнать, от каких потоков были получены сообщения (смотри рисунок N3).

Последнее усовершенствование, которое хочется предложить, это организация показа уровня вложенности сообщений при вызове функций или начале логического блока. Это можно легко организовать, используя специальный класс который в конструкторе записывает в лог идентификатор начала блока, а в деструкторе — идентификатор конца блока. Написав небольшую утилитку, можно трансформировать лог, опираясь на информацию об идентификаторах. Попробуем показать это на примере.

Лог после трансформации:

Пожалуй, на этом можно закончить. Последнее о чем хочется еще упомянуть, это статья «Logging In C++» [11], которая также может Вам пригодиться. Желаем Вам удачной отладки.

4. Использование правильных типов данных с точки зрения 64-битных технологий.

Использование соответствующих аппаратной платформе базовых типов данных в языке Си/Си++ является важным элементом для создания качественных и высокопроизводительных программных решений. С приходом 64-битных систем начали использоваться новые модели данных — LLP64, LP64, ILP64 (см. таблицу N1), что изменило правила и рекомендации использования базовых типов данных. К таким типам можно отнести int, unsigned, long, unsigned long, ptrdiff_t, size_t и указатели. К сожалению, вопросы выбора типов практически не освещены в популярной литературе и статьях. А те источники, в которых они освещены, например «Software Optimization Guide for AMD64 Processors» [12], редко читают прикладные программисты.

Актуальность правильного выбора базовых типов для обработки данных обусловлена двумя важными причинами: корректностью работы кода и его эффективностью.


Исторически сложилось, что базовым и наиболее используемым целочисленным типом в языке Си и Си++ является int или unsigned int. Принято считать, что использование типа int является наиболее оптимальным, так как его размер совпадает с длиной машинного слова процессора. Машинное слово — это группа разрядов оперативной памяти, выбираемая процессором за одно обращение (или обрабатываемая им как единая группа), обычно содержит 16, 32 или 64 разряда.

Традиция делать размер типа int равным размеру машинного слова до недавнего времени нарушалась редко. На 16-битных процессорах int состоял из 16 бит. На 32-битных процессорах — 32 бита. Конечно, существовали и иные соотношения размера int и машинного слова, но они использовались редко и не представляют сейчас для нас интереса.

Нас интересует тот факт, что с приходом 64-битных процессоров размер типа int в большинстве систем остался равен 32-битам. Тип int имеет размер 32 бита в моделях данных LLP64 и LP64, которые используются в 64-битных операционных системах Windows и большинстве Unix систем (Linux, Solaris, SGI Irix, HP UX 11).

Оставить размер типа int равным 32-м битам является плохим решением по многим причинам, но оно является обоснованным выбором меньшего среди других зол. В первую очередь оно связано с вопросами обеспечения обратной совместимости. Более подробно о причинах такого выбора можно прочесть в блоге «Why did the Win64 team choose the LLP64 model?» и статью «64-Bit Programming Models: Why LP64?».

Для разработчиков 64-битных приложений все вышесказанное является предпосылкой придерживаться двух новых рекомендаций в процессе разработки программного обеспечения.

Рекомендация 1. Использовать для счетчиков циклов и адресной арифметики типы ptrdiff_t и size_t, вместо int и unsigned.

Рекомендация 2. Использовать для индексации в массивах типы ptrdiff_t и size_t, вместо int и unsigned.

Другими словами, по возможности использовать типы данных, которые на 64-битной системе имеют размер 64-бита. Отсюда следует утверждение, что не следует больше использовать конструкции вида:

Да, это канонический пример кода. Да, его много во множестве программ. Да с него начинают обучению языку Си и Си++. Но больше его использовать не рекомендуется. Используйте либо итераторы, либо типы данных ptdriff_t и size_t, как показано в улучшенном примере:

Разработчики Unix-приложений могут сделать замечание, что уже достаточно давно возникла практика использования типа long для счетчиков и индексации массивов. Тип long является 64-битным в 64-битных Unix-системах и его использование выглядит более элегантным, чем ptdriff_t или size_t. Да это так, но следует учесть два важных обстоятельства.

1) В 64-битных операционных системах Windows размер типа long остался 32-битным (см. таблицу N1). И, следовательно, он не может быть использован вместо типов ptrdiff_t и size_t.

2) Использование типов long и unsigned long еще больше усложняет жизнь разработчиков кросс-платформенных приложений для Windows и Linux систем. Тип long имеет в этих системах разный размер и только добавляет путаницы. Лучше придерживаться типов, имеющих одинаковый размер в 32-битных и 64-битных Windows и Linux системах.

Пришло время на примерах пояснить, почему так настойчиво рекомендуется отказаться от привычного использования типа int/unsigned в пользу ptrdiff_t/size_t.

Начнем мы с примера, демонстрирующего классическую ошибку использования типа unsigned для счетчика цикла в 64-битном коде. Мы уже описывали выше аналогичный пример, но повторим его еще раз в силу распространенности данной ошибки:

Это типичный код, варианты которого можно встретить во многих программах. Он корректно выполняется в 32-битных системах, где значение переменной Count не может превысить SIZE_MAX (который равняется в 32-битной системе UINT_MAX). В 64-битной системе диапазон возможных значений для Count может быть увеличен и тогда при значении Count > UINT_MAX возникнет вечный цикл. Корректным исправлением данного кода использование вместо типа unsigned типа size_t.

Следующий пример демонстрирует ошибку использования типа int для индексации больших массивов:

Этот код обычно не вызывает никаких подозрений у прикладного разработчика, привыкшего к практике использования в качестве индексов массивов переменные типа int или unsigned. К сожалению, приведенный код на 64-битной системе будет неработоспособен, если объем обрабатываемого массива BigArray превысит размер в четыре миллиарда элементов. В этом случае произойдет переполнение переменной Index, и результат работы программы будет некорректен (будет заполнен не весь массив). Корректировка кода вновь заключена в использовании для индексов типа ptrdiff_t или size_t.

В качестве последнего примера, хочется продемонстрировать потенциальную опасность смешенного использования 32-битных и 64-битных типов, которого следует по возможности избегать. К сожалению не многие разработчики задумываются, к чему может привести неаккуратная смешенная арифметика и для многих следующий пример оказывается неожиданностью (результаты получены с использованием Microsoft Visual C++ 2005 , 64-битный режим компиляции):

Хочется обратить внимание, что выражение вида «intptr_t v2 = intptr_t(x) * y * z;» вовсе не гарантирует правильный результат. Оно гарантирует только то, что выражение «intptr_t(x) * y * z» будет иметь тип intptr_t. Более подробно с этими вопросом поможет разобраться статья «20 ловушек переноса Си++ — кода на 64-битную платформу» [4].

Теперь перейдем к примеру, демонстрирующему преимущества использования типов ptrdiff_t и size_t с точки зрения производительности. Для демонстрации возьмем простой алгоритм вычисления минимальной длинны пути в алгоритме. С полным кодом программы можно познакомиться по ссылке: http://www.Viva64.com/articles/testspeedexp.zip.

В статье для краткости приведен только текст функций FindMinPath32 и FindMinPath64. Обе эти функции высчитывают длину минимального пути между двумя точками в лабиринте. Остальной код не представляет сейчас интереса.

Функция FindMinPath32 написана в классическом 32-бином стиле с использованием типов unsigned. Функция FindMinPath64 отличается от нее только тем, что в ней все типы unsigned заменены на типы size_t. Других отличий нет! Согласитесь, что это не является сложной модификацией программы. А теперь сравним скорости выполнения этих двух функций (см. таблицу N2).

Режим и функция. Время работы функции
1 32-битный режим сборки. Функция FindMinPath32 1
2 32-битный режим сборки. Функция FindMinPath64 1.002
3 64-битный режим сборки. Функция FindMinPath32 0.93
4 64-битный режим сборки. Функция FindMinPath64 0.85
Таблица N2. Время выполнения функций FindMinPath32 и FindMinPath64.

В таблице N2 показано приведенное время относительно скорости выполнения функции FindMinPath32 на 32-битной системе. Это сделано для большей наглядности.

В первой строке время работы функции FindMinPath32 на 32-битной системе равно 1. Это вызвано тем, что мы взяли как раз ее время работы за единицу измерения.

Во второй строке мы видим, что время работы функции FindMinPath64 на 32-битной системе также равно 1. Это не удивительно, так как на 32-битной системе тип unsigned совпадает с типом size_t и никакой разницы между функцией FindMinPath32 и FindMinPath64 нет. Небольшое отклонение (1.002) говорит только о небольшой погрешности в измерениях.

В третье строке мы видим прирост производительности равный 7%. Это вполне ожидаемый результат от перекомпиляции кода для 64-битной системы.

Наибольший интерес представляет 4 строка. Прирост производительности составляет 15%. Это значит, что простое использование типа size_t вместо unsigned позволяет компилятору построить более эффективный код, работающий еще на 8% быстрее!

Это простой и наглядный пример, когда использование данных, не равных размеру машинного слова снижает производительность алгоритма. Простая замена типов int и unsigned на типы ptrdiff_t и size_t может дать существенный прирост производительности. В первую очередь это относится к использованию этих типов данных для индексации массивов, адресной арифметики и организации циклов.

Хочется надеяться после всего вышесказанного, Вы задумаетесь, стоит ли продолжать писать:

Для автоматизации поиска ошибок в 64-бином коде, разработчики Windows-приложений могут обратить внимание в сторону статического анализатора кода Viva64 [8]. Во-первых, его использование позволит выявить большинство ошибок. Во-вторых, разрабатывая программы под его контролем, Вы станете реже использовать 32-битных переменные, будете избегать смешанной арифметики с 32-битными и 64-битными типами данных, что автоматически увеличит производительность Вашего кода. Для разработчиков под Unix системы интерес могут представлять статические анализаторы Gimpel Software PC-Lint и Parasoft C++test. Они способны диагностировать ряд 64-битных ошибок в коде с моделью данных LP64, используемой в большинстве Unix-систем.

Более подробно, Вы можете познакомиться с вопросами разработки качественного и эффективного 64-битного кода в следующих статьях: «Проблемы тестирования 64-битных приложений», «24 Considerations for Moving Your Application to a 64-bit Platform», «Porting and Optimizing Multimedia Codecs for AMD64 architecture on Microsoft Windows», «Porting and Optimizing Applications on 64-bit Windows for AMD64 Architecture».

5. Дополнительные способы повышения производительности программных систем.

В последней части этой статьи хочется рассмотреть еще несколько технологий, которые могут быть Вам полезны при разработке ресурсоемких программных решений.

5.1. Intrinsic-функции.

Intrinsic-функции это специальные системно-зависимые функции, выполняющие действия, которые невозможно выполнить на уровне Си/Си++ кода или которые выполняют эти действия намного эффективнее. По сути, они позволяют избавиться от использования inline-ассемблера, т.к. его использование часто нежелательно или невозможно.

Программы могут использовать intrinsic-функции для создания более быстрого кода за счет отсутствия накладных расходов на вызов обычного вида функций. При этом, естественно, размер кода будет чуть-чуть больше. В MSDN приводится список функций, которые могут быть заменены их intrinsic-версией. Это, например, memcpy, strcmp и другие.

В компиляторе Microsoft Visual C++ есть специальная опция «/Oi», которая позволяет автоматически заменять вызовы некоторых функций на intrinsic-аналоги.

Помимо автоматической замены обычных функций на intrinsic-варианты, можно явно использовать в коде intrinsic-функции. Вот для чего это может быть нужно:

  • Встроенный (inline) ассемблерный код не поддерживается компилятором Visual C++ в 64-битном режиме. Intrinsic-код поддерживается.
  • Intrinsic-функции проще использовать, так как они не требуют знания регистров и других подобных низкоуровневых конструкций.
  • Intrinsic-функции обновляются в компиляторах. Ассемблерный же код придется обновлять вручную.
  • Встроенный оптимизатор не работает с ассемблерным кодом, поэтому требуется внешняя линковка модуля. Для intrinsic-кода такого не нужно.
  • Intrinsic-код легче переносить, чем ассемблерный.

Использование intrinsic-функций в автоматическом режиме (с помощью ключа компилятора) позволяет получить бесплатно несколько процентов прироста производительности, а «ручное» — даже больше. Поэтому использование intrinsic-функций вполне оправдано.

Более подробно с применением intrinsic-функций можно ознакомиться в блоге команды Visual C++ [21].

5.2. Упаковка и выравнивание данных.

Выравнивание данных в последнее время не так сильно сказывается на производительности кода, как, скажем, 10 лет назад. Однако иногда и тут можно получить дополнительный выигрыш в экономии памяти и производительности.

В 32-битном режиме данная структура занимает 12 байт, но в 64-битном — уже 24 байта. Для того чтобы в 64-битном режиме структура занимала положенные ей 16 байт следует изменить порядок следования полей:

В некоторых случаях полезно явно помогать компилятору, задавая выравнивание вручную, чтобы увеличить производительность. Например, данные SSE должны быть выровнены по границе 16 байт. Вот как этого можно добиться:

Источники «Porting and Optimizing Multimedia Codecs for AMD64 architecture on Microsoft Windows», » Porting and Optimizing Applications on 64-bit Windows for AMD64 Architecture» [20] дают подробный обзор данных вопросов.


5.3. Файлы, отображаемые в память.

С появлением 64-битных систем технология отображения файлов в память стала более привлекательной в использовании, так как увеличилось окно доступа к данным. Для некоторых приложений это может быть очень полезным приобретением. Не забывайте о нем.

5.4. Ключевое слово __restrict.

Одна из наиболее серьезных проблем для компилятора — это совмещение (aliasing) имен. Когда код читает и пишет память, часто на этапе компиляции невозможно определить, получает ли к данной области памяти доступ более чем один указатель. То есть, может ли более чем один указатель «синонимом» для одной и той же области памяти. Поэтому, например, внутри цикла, в котором и читается, и пишется память, компилятор должен быть очень осторожен с хранением данных в регистрах, а не в памяти. Это недостаточно активное использование регистров может существенно повлиять на производительность.

Ключевое слово __restrict используется для того, чтобы облегчить компилятору принятие решения. Оно говорит компилятору «быть смелее» с использованием регистров.

Ключевое слово __restrict позволяет компилятору не считать отмеченные указатели синонимичными (aliased), то есть ссылающимися на одну и ту же область памяти. Компилятор в таком случае может произвести более эффективную оптимизацию. Рассмотрим пример:

В данном коде компилятор может безопасно хранить сумму в регистре, связанном с переменной «a», избегая записи в память. Хорошим источником информации об использовании ключевого слова __restrict является MSDN.

5.5. SSE-инструкции.

Приложения, запускаемые на 64-битных процессорах (независимо от режима) будут работать более эффективно, если в них используются SSE-инструкции вместо MMX/3DNow. Это связанно с разрядностью обрабатываемых данных. SSE/SSE2 инструкции оперируют 128-битными данными, в то время как MMX/3DNow — только лишь 64-битными. Поэтому код, использующих MMX/3DNow, лучше переписать с ориентацией на SSE.

В данной статье мы не будем останавливаться на SSE-инструкциях, отсылая интересующихся читателей к документации от разработчиков процессорных архитектур.

5.6. Определенные правила использования языковых инструкций.

64-битная архитектура приносит новые возможности для оптимизации на уровне отдельных операторов языка программирования. Это уже ставшие традиционными приемы по «переписыванию» кусочков программы с тем, чтобы компилятор еще лучше их оптимизировал. Рекомендовать к массовому использованию эти приемы, конечно же, не стоит, но знать о них может быть полезно.

На первом месте из целого списка данных оптимизаций стоит ручное разворачивание циклов (unroll the loop). Суть данного метода легко увидеть из примера:

Во многих случаях, компилятор сам может развернуть цикл до такого представления (ключ /fp:fast для Visual C++), но не всегда.

Другой синтаксической оптимизацией является использование массивной (от слова «массив») нотации вместо указательной (от слова «указатель»).

Множество подобных приемов приведено в «Software Optimization Guide for AMD64 Processors».

Заключение.

Несмотря на то, что при создании программных систем, эффективно использующих аппаратные возможности современной вычислительной техники, придется столкнуться с большим количеством трудностей, игра стоит свеч. Параллельные 64-битные системы открывают новые возможности в построении настоящих масштабируемых решений. Они позволяют поднять на новый уровень возможности современных программных средств в обработке данных, будь то игры, CAD-системы или распознавание образов. Желаем Вам удачи в освоении новых технологий!

Ссылки по теме

Популярные статьи
Информационная безопасность Microsoft Офисное ПО Антивирусное ПО и защита от спама Eset Software


Бестселлеры
Курсы обучения «Atlassian JIRA — система управления проектами и задачами на предприятии»
Microsoft Office 365 для Дома 32-bit/x64. 5 ПК/Mac + 5 Планшетов + 5 Телефонов. Подписка на 1 год. Электронный ключ
Microsoft Windows 10 Профессиональная 32-bit/64-bit. Все языки. Электронный ключ
Microsoft Office для Дома и Учебы 2020. Все языки. Электронный ключ
Курс «Oracle. Программирование на SQL и PL/SQL»
Курс «Основы TOGAF® 9»
Microsoft Windows Professional 10 Sngl OLP 1 License No Level Legalization GetGenuine wCOA (FQC-09481)
Microsoft Office 365 Персональный 32-bit/x64. 1 ПК/MAC + 1 Планшет + 1 Телефон. Все языки. Подписка на 1 год. Электронный ключ
Windows Server 2020 Standard
Курс «Нотация BPMN 2.0. Ее использование для моделирования бизнес-процессов и их регламентации»
Антивирус ESET NOD32 Antivirus Business Edition
Corel CorelDRAW Home & Student Suite X8

О нас
Интернет-магазин ITShop.ru предлагает широкий спектр услуг информационных технологий и ПО.

На протяжении многих лет интернет-магазин предлагает товары и услуги, ориентированные на бизнес-пользователей и специалистов по информационным технологиям.

Хорошие отзывы постоянных клиентов и высокий уровень специалистов позволяет получить наивысший результат при совместной работе.

Выполнение модульного теста как 64-разрядного процесса Run a unit test as a 64-bit process

Эта статья относится к Visual Studio 2015. This article applies to Visual Studio 2015. Если вы ищете последние версии документации Visual Studio, используйте средство выбора версии в верхнем левом углу. If you’re looking for the latest Visual Studio documentation, use the version selector at the top left. Мы рекомендуем выполнить обновление до Visual Studio 2020. We recommend upgrading to Visual Studio 2020. Скачать эту версию можно здесь Download it here

На 64-разрядном компьютере можно выполнять модульные тесты и получать данные о покрытии кода в рамках 64-разрядного процесса. If you have a 64-bit machine, you can run unit tests and capture code coverage information as a 64-bit process.

Выполнение модульного теста как 64-разрядного процесса Running a unit test as a 64-bit process

Выполнение модульного теста как 64-разрядного процесса To run a unit test as a 64-bit process

Если код или тесты были скомпилированы как 32-разрядные (x86), но вы хотите выполнять их в 64-разрядном процессе, перекомпилируйте их в конфигурации Любой ЦП или при необходимости 64 разряда. If your code or tests were compiled as 32-bit/x86, but you now want to run them as a 64-bit process, recompile them as Any CPU, or optionally as 64-bit.

Для максимальной гибкости тестовые проекты следует компилировать в конфигурации Любой ЦП. For maximum flexibility, you should compile your test projects with the Any CPU configuration. Тогда выполнение возможно как на 32-разрядных, так и на 64-разрядных агентах. Then you can run on both 32 and 64 bit agents. Компиляция тестовых проектов в конфигурации 64 разряда не дает никаких преимуществ. There is no advantage to compiling test projects with the 64-bit configuration.

В меню Visual Studio выберите Тест, а затем Параметры и Архитектура процессора. From the Visual Studio menu, choose Test, then choose Settings, and then choose Processor Architecture. Выберите x64, чтобы выполнять тесты в 64-разрядном процессе. Choose x64 to run the tests as a 64-bit process.

Укажите x64 в RUNSETTINGS-файле. Specify x64 in a .runsettings file. Преимущество этого метода состоит в том, что можно задавать группы настроек в разных файлах и быстро переключаться между различными настройками. An advantage of this method is that you can specify groups of settings in different files and quickly switch between different settings. Кроме того, вы можете копировать настройки между решениями. You can also copy settings between solutions. Дополнительные сведения см. в разделе Настройка модульных тестов с помощью файла .runsettings. For more information, see Configure unit tests by using a .runsettings file.

Компьютерные сети

Многоуровневая архитектура Интернета

Урок 07. Проблемы выявления 64-битных ошибок

Существуют различные подходы к выявлению ошибок в программном коде. Рассмотрим основные методологии и их эффективность в выявлении 64-битных ошибок.

Самым старым, проверенным и надежным подходом к поиску дефектов является совместный обзор кода (англ. code review). Эта методика основана на совместном чтении кода с выполнением ряда правил и рекомендаций, хорошо описанных в книге Стива Макконнелла «Совершенный код» (Steve McConnell, «Code Complete»). К сожалению, эта практика неприменима для крупномасштабной проверки современных программных систем в силу их большого объема.

Обзор кода в данном случае скорее можно рассматривать как хороший способ обучения и защиты от 64-битных ошибок в новом разрабатываемом коде. Для выявления же уже имеющихся ошибок данный способ неприемлем из-за его стоимости. Вам придется совместно внимательно прочитать весь код программного проекта, чтобы обнаружить все 64-битные ошибки.

Статический анализ кода

На помощь разработчикам, которые осознают необходимость регулярного просмотра кода, но не имеют достаточного количества времени, приходят средства статического анализа кода. Их основной задачей является сокращение объема кода, требующего внимания человека, и тем самым сокращение времени его просмотра. К статическим анализаторам кода относится достаточно большой класс программ, реализованных для различных языков программирования и имеющих разнообразный набор функций, от простейшего контроля выравнивания кода, до сложного анализа потенциально опасных мест. Преимуществом статического анализа является его хорошая масштабируемость. С его помощью можно в разумные сроки проанализировать проект любого объема. А систематическое использование анализаторов позволяет выявлять многие ошибки еще на этапе написания кода.

Метод статического анализа является наиболее оптимальным решением для выявления 64-битных ошибок. В дальнейшем, рассматривая паттерны 64-битных ошибок, мы будем показывать, как данные ошибки можно диагностировать, используя статический анализатор Viva64, входящий в состав PVS-Studio. В следующем уроке вы также подробнее познакомитесь с методологией статического анализа и инструментом PVS-Studio.

Метод белого ящика

Под тестированием методом белого ящика будем понимать выполнение максимально доступного количества различных веток кода с использованием отладчика или иных средств. Чем большее покрытие кода было достигнуто, тем более полно выполнено тестирование. Под тестированием по методу белого ящика также иногда понимают простую отладку приложения с целью поиска известной ошибки. Полноценное тестирование методом белого ящика всего кода программ уже давно стало невозможным в силу огромного размера современных программ. Сейчас тестирование по методу белого ящика удобно применять на этапе, когда ошибка найдена, и необходимо понять причину ее возникновения. У тестирования методом белого ящика существуют оппоненты, отрицающие полезность отладки программ в реальном времени. Основной мотив заключается в том, что возможность наблюдать ход работы программы и при этом вносить изменения в ее состояние порождает недопустимый подход в программировании, основанный на большом количестве исправлений кода методом проб и ошибок. Мы не будем касаться данных споров, но заметим, что тестирование по методу белого ящика в любом случае очень дорогой способ повышения качества больших программных систем.

Читателю должно быть очевидно, что полная отладка приложения для выявления 64-битных ошибок также нереальна, как и полный обзор программного кода.

Дополнительно стоит заметить, что при отладке 64-битных приложений, обрабатывающих большие массивы данных, способ пошаговой отладки может стать неприменимым. Отладка таких приложений может занимать намного больше времени. Стоит заранее обдумать возможность использования систем протоколирования («логирования») для отладки приложений или предусмотреть иные методы.

Метод черного ящика (юнит-тесты)

Намного лучше себя зарекомендовал метод черного ящика. К этому типу тестирования можно отнести юнит-тестирование (unit tests). Основная идея метода заключается в написании набора тестов для отдельных модулей и функций, проверяющего все основные режимы их работы. Ряд источников относят юнит-тестирование к методу белого ящика, поскольку оно основывается на знании устройства программы. Мы придерживаемся позиции, что тестируемые функции и модули следует рассматривать как черные ящики, так как юнит-тесты не должны учитывать внутреннее устройство функции. Обоснованием этому может служить такая методология, когда тесты разрабатываются до начала написания самих функций, что способствует повышению контроля их функциональности с точки зрения спецификации.


Юнит-тестирование хорошо зарекомендовало себя как при разработке простых, так и сложных проектов. Одним из преимуществ юнит-тестирования является то, что легко можно проверить корректность вносимых в программу исправлений прямо в ходе разработки. Стараются делать так, чтобы все тесты проходили в течение нескольких минут, что позволяет разработчику, который внес изменения в код, сразу заметить ошибку и исправить ее. Если прогон всех тестов невозможен, то обычно длительные тесты выносят отдельно и запускают, например, ночью. Это также способствует оперативному обнаружению ошибок, по крайней мере, на следующее утро.

C использованием юнит-тестов для поиска 64-битных ошибок связан ряд неприятных моментов. Стремясь сократить время выполнения тестов, при их разработке стараются использовать небольшой объем вычислений и объем обрабатываемых данных. Например, разрабатывая тест на функцию поиска элемента в массиве, не имеет большого значения, будет она обрабатывать 100 элементов или 10 000 000. Сотни элементов будет достаточно, а вот по сравнению с обработкой 10 000 000 элементов скорость выполнения теста может быть существенно выше. Но если вы хотите разработать полноценные тесты, чтобы проверить эту функцию на 64-битной системе, вам потребуется обработать более 4 миллиардов элементов! Вам кажется, что если функция работает на 100 элементах, она будет работать и на миллиардах? Нет. Приведем пример.

Мой блог находят по следующим фразам

Уточнения, корректировки и обсуждения статьи «Урок 07. Проблемы выявления 64-битных ошибок» — под данным текстом, в комментариях.

Ответственность, за все изменения, внесённые в систему по советам данной статьи, Вы берёте на себя.

Тестируем оперативную память на работоспособность

Сбои в работе компьютера происходят по многим причинам. Виноват может быть любой компонент системы, в том числе и ОЗУ. Расскажем в этой статье, как проверить оперативную память на ошибки.

Что собой представляет оперативная память и для чего она предназначена

Оперативная память сокращенно называется ОЗУ (оперативное запоминающее устройство) либо RAM — по-английски память произвольного (случайного) доступа, на сленге ее часто именуют «оперативка». Ниже представлен один из вариантов ее исполнения.

Процессор выполняет вычисления, но нужно сохранять промежуточные результаты. Кто помнит начальные классы в школе: «семь пишем, два в уме». Для этого и служит ОЗУ. Это обязательный элемент любой вычислительной машины. Первоначально RAM собирали на магнитных сердечниках и тому подобное, а объем записываемой в нее информации был минимален. Сейчас оперативная память представляет собой набор микросхем с довольно большой емкостью. В компьютерах существует еще один тип памяти — ПЗУ (постоянное запоминающее устройство), на нем хранится прошивка БИОС.

ОЗУ отличается от него тем, что зависит от напряжения питания, при выключении ПК все записанные байты стираются. Емкость оперативки для современных вычислений нужна относительно большая, несколько Гб, также немаловажна скорость обмена данными. Различают два типа ОЗУ — SRAM и DRAM, со статическим и динамическим доступом соответственно. Первый тип основывается на том, что каждый бит хранится в отдельном триггере — ячейке из двух транзисторов. Данный вид памяти компьютера размещает гораздо меньше информации на единице площади кристалла, зато меньше подвержен повреждениям, и записанные данные остаются неизменными без дополнительных операций до снятия питания со схемы. Используется он больше всего во внутренней памяти процессора, называемой кэшем и располагается на его кристаллах. Нас же интересует непосредственно ОЗУ компьютера. Работает она с использованием динамического доступа (DRAM), а для хранения информации используются конденсаторы. Такой подход позволяет значительно увеличить емкость на единицу площади, но несколько увеличивает вероятность выхода некоторого количества ячеек хранения из строя при нештатных ситуациях, таких как «стресс» в виде перенапряжения, перегрева и тому подобное.

Симптомы повреждения ОЗУ

Признаками того, что возможно возникли проблемы с оперативной памятью, являются частые вылеты компьютера в синий экран смерти для XP, для Windows 8, 10 он может быть и черным.

Причем, наиболее часто сбои происходят при работе с ресурсоемкими приложениями, которыми являются игры, графические редакторы. Коды ошибки при этом все время меняются. Также может наблюдаться нечеткое мерцающее изображение на экране. Компьютер может вообще не загружаться, подавая звуковые сигналы, их можно расшифровать согласно инструкции к материнской плате. Но все эти признаки не обязательно указывают на оперативную память, может быть виновата видеокарта или процессор, маломощный блок питания. Стоит провести тест оперативной памяти Windows, он поможет локализовать причину неисправности. К тому же, зная что виновата ОЗУ, можно легко провести ремонт самостоятельно. Иногда причина сбоя даже не в самом блоке микросхем очистки памяти, а в плохом контакте на разъеме.

Тест оперативной памяти на компьютерах с Windows 7 и выше

Эта операционная система имеет встроенные средства, которыми проводится проверка оперативной памяти на ошибки. Поэтому необязательно искать и устанавливать сторонний софт. Сам процесс занимает немного времени. Еще стоит отметить такую особенность Windows 7 (64- или 32-битные) и более новых версий, как самодиагностика, то есть, обнаружив неполадки в системе, она сама предложит протестировать оперативную память. Если увидите такое сообщение, то не стоит отказываться.

Также можно проверить работоспособность оперативной памяти вручную, для этого используем один из способов:

  • Заходим в Панель управления, нажав Пуск. Там выбираем «Администрирование», а затем «Средство проверки памяти Windows».
  • Перед началом запуска операционной системы нажимаем клавишу F2 . Компьютер предложит запустить Windows либо программу проверки памяти. С помощью Tab выбираем последнее и нажимаем ввод. Запустится проверка памяти. Этот вариант единственный, если операционная система не загружается вообще.
  • Заходим в меню Пуск, в панели поиска программ набираем «mdsched». Появится окошко с иконкой для запуска средства проверки памяти.
  • Щелкаем по иконке с надписью «MdSched» и запускается программа для тестирования оперативной памяти.

Программа спрашивает о том, когда провести проверку, сейчас или при следующем включении компьютера. Выбираем нужный вариант. При этом не забываем, что при перезагрузке рискуем потерять все несохраненные файлы. Программа автоматически включает принудительное закрытие приложений, не давая времени на отмену решения. Поэтому страхуемся и корректно закрываем все работающие программы. Windows закрывается и начинается процедура проверки.

Нажав на клавишу F1 можно выбрать дополнительные параметры проверки:

  • Набор тестов: базовый, стандартный или расширенный. Без дополнительных параметров система выбирает стандартный режим. Базовый ускорит процесс, но сделает его менее тщательным. Расширенный наоборот затянет время, но проверит каждую ячейку досконально.
  • Кэш по умолчанию включен, но можно выключить. С отключенным кэшем время, за которое проводится диагностика оперативной памяти, увеличится в несколько раз.
  • Количество проходов. Автоматически выбирается два, но можно задать любое количество от 1 до 99. Это повлияет на качество и время проведения проверки. В один проход проверка будет менее качественная. Но проходы больше трех не выявляют дополнительных проблем. Не вводите цифру 0, в этом случае тестирование оперативной памяти будет продолжаться бесконечно.

Навигация в меню осуществляется клавишами Tab для перехода между пунктами и стрелками для выбора параметра. Количество проходов набираем на цифровой клавиатуре, удалив перед этим стандартную двойку. Запуск после выбора параметров теста осуществляется с помощью F10 .

Начнется процесс проверки памяти, он занимает, в зависимости объема ОЗУ, до получаса времени. При этом на экране постоянно отображается ход процесса: сколько процентов проверено, какой проход производится, обнаружены ли проблемы. Если нужно прервать тест (срочно понадобился компьютер), то нажмите ESC . После прерывания придется начать все заново, включая уже пройденные блоки.

По окончании работы программы компьютер начнет автоматически запускать операционную систему. Причем ей на это требуется больше времени, чем при штатной процедуре. После загрузки ПК, на Панели задач появится уведомление о результатах проверки. Но стоит обратить внимание на то, что оно может не появиться вообще, если проблем не обнаружено, а вывешивается всего на пару минут. Если запустили проверку и пошли пить чай на кухню, то можно прозевать. В этом случае поможет «Просмотр событий» в меню Панели управления в разделе «Администрирование». Находим там «Журналы Windows» среди них «Система» и в списке сведений «MemoryDiagnostics-Result».

Как проверить ОЗУ с помощью утилит

Чтобы проверить оперативную память на работоспособность на ПК или на ноутбуке с ОС Windows XP и более ранней версией (такие еще встречаются), необходимо воспользоваться специальными программами. Кроме того, многие из этих программ предлагают более широкий набор тестов, чем стандартное средство Майкрософт. В интернете большинство их можно скачать быстро и бесплатно. При выборе нужно учитывать следующие факторы:

  • Есть программы запускающиеся из Виндовс. С ними работать проще — скачал, установил, некоторые работают и без установки, проверил. Но они не подходят для случаев, когда проблемы с операционной системой. Также проверка из БИОСа более точная. Правда понадобится их копирование на флешку или диск.
  • Многие утилиты, особенно созданные давно, не могут работать с ОЗУ более четырех Гбайт. Если памяти больше (версии 64 bit такое позволяют), то придется проверять ее частями, вынимая планки, а это лишние хлопоты.

Для примера рассмотрим, как работать с одной из распространенных бесплатных утилит Memtest86+ или ей подобными программами. Необходимо выполнить последовательность действий:

  1. Скачиваем образ диска из интернета.
  2. Создаем загрузочную флешку или диск, что в наше время это несерьезно и отнимает лишнее время. Для этого существуют специальные программы, например Rufus.
  3. При запуске компьютера в БИОС выбираем не диск с операционной системой, а загрузку нашей утилиты.
  4. Смотрим на экране результаты: Errors — обнаруженные ошибки. В большинстве случаев проверку можно прервать, нажав ESC .

Оформление окна, в котором выводятся результаты проверки, может быть другим, но все должно быть понятно интуитивно.

Если проблемы обнаружены

Небольшие повреждения ОЗУ могут не влиять на работу компьютера, просто уменьшится объем памяти, и несколько снизится производительность. Но если проблемы уже возникли, и тест памяти показал неисправность, необходим ремонт. Конечно, если компьютер на гарантии и опломбирован, то обращаемся в сервисный центр или к продавцу. Если же нет и вы уверены в своих возможностях, то можно произвести ремонт самостоятельно. Выполняем следующие действия:

  1. Находим планки с оперативной памятью. У настольного компьютера снимаем боковую крышку. У ноутбука нижнюю панель или у большинства моделей только часть ее с надписью или пиктограммой, обозначающей память. Место установки можно посмотреть в руководстве к материнской плате, но найти ОЗУ легко и без него. Установленные вертикально длинные платы с рядами одинаковых микросхем это и есть планки ОЗУ настольного компьютера. У ноутбука они меньшие по размеру и располагаются в несколько ярусов параллельно материнской плате.
  2. Для начала проверим, не виноваты ли контакты, может микросхемы тут не причем. Освободив защелки по краям планок, извлекаем их. Контакты ни в коем случае нельзя зачищать наждачной бумагой или ножом, так стирается защитный слой золота. Для удаления окислов используем ластик для карандашей. После очистки обезжириваем спиртом. Устанавливаем планки обратно. Неправильно это сделать невозможно из-за вырезов ключей. Защелки фиксируют их автоматически. Снова тестируем. Возможно, проблемы исчезнут.
  3. Если чистка контактов не помогла, то придется менять планки. Причем, если их несколько, то проверки ОЗУ необходимо выполнять по одной планке, извлекая остальные, чтобы найти неисправную плату. Выбирая замену, ориентируемся не только на объем, но и на скорость считывания, она должна поддерживаться вашей материнской платой.

Заключение

Будем рады, если наша небольшая статья помогла проверить оперативную память компьютера и решить возникшие с ней проблемы. Мы рассказали, как проверить оперативную память компьютера встроенными в операционную систему методами. Также рассмотрели, что для проверки оперативной памяти устаревших версий Windows необходимо воспользоваться специальным ПО, которое имеет множество дополнительных возможностей и может быть применено на более новых версиях. Для примера была взята программа проверки оперативной памяти Memtest86+.

Programming stuff

Страницы

понедельник, 28 марта 2011 г.

Проблемы запуска .Net приложений под 64-битными ОС

Я уже второй раз за последнее время сталкиваюсь с разными проблемами запуска «управляемых» приложений под 64-битным операционками, так что думаю, пришло время немного об этом рассказать.

Итак, программирование на платформе .Net делает еще один шаг по отделению прикладного программиста от всяких низкоуровневых платформенно-зависимых вещей типа размеров указателя, выравнивания, размеров целочисленных типов данных и других проблем, характерных для программирования на неуправляемых С/С++. Теперь все становится значительно проще и компиляторы таких языков программирования как C# или VB.Net не генерируют ассемблерные инструкции напрямую (хотя такая возможность и присутствует), вместо этого, результатом компиляции является код на промежуточном языке программирования, который затем компилируется во время выполнения JIT-компилятором в набор инструкций для конкретной платформы.

Если говорить за .Net 1.0 и 1.1, то в те старые добрые времена существовала только лишь 32-х разрядная версия CLR, что приводило к запуску .Net приложений на 64-х битных операционных системах в режиме совместимости (WOW64). Начиная с .Net 2.0 у разработчика появилась возможность выбора «целевой платформы» (Target platform), для которой это приложение предназначено. Обычно, этот выбор сводится к одному из следующих вариантов:

  • Any CPU – конкретная платформа будет выбрана автоматически при запуске приложения;
  • x86 – это старый добрый 32-х битный режим для процессоров семейства x86;
  • x64 – это новый модный режим для 64-х битных процессоров;
  • Itanium – а это старый и немодный режим для процессоров Itanium.


Все эти новшества полезны и замечательны, пока речь не заходит о взаимодействии с неуправляемым кодом, написанным на «чистом» С/С++. В таком случае, ваше приложение может сколько угодно говорить, что оно предназначено для “Any CPU”, но если одна из сборок использует неуправляемую dll, заточенную под определенную платформу, то чтобы заставить работать его под другой платформой придется попотеть.

64-х битная ОС и 32-х битная неуправляемая dll

Давайте рассмотрим следующую ситуацию: у нас есть «управляемое приложение», скомпилированное под “Any CPU”, при этом одна из сборок этого приложения использует неуправляемую 32-х битную dll (рисунок 1). За примером далеко ходить не нужно, поскольку многие существующие библиотеки все еще опираются на «нативные» реализации; так, например, многие драйвера доступа к базам данных, а также компоненты для работы с картами, реализованы именно таким образом.

Рисунок 1 – Запуск приложения с 32-х битной неуправляемой dll

Итак, при запуске приложения, операционная система проверяет информацию в заголовке исполняемого файла, чтобы определить в каком режиме его запускать: в режиме совместимости с 32-х битными приложения (т.е. в WOW64 режиме), или запускать его, как полноценное 64-х битное приложение. Если «управляемое» приложение собрано под “Any CPU”, то логично предположить, что будет выбран «честный» 64-х битный режим, который не требует никаких дополнительных «прослоек» (какой является режим WOW64), что позволит полностью воспользоваться всеми возможностями 64-х битной операционной системы. В результате будет запущена 64-х битная версия CLR, которая будет компилировать IL-код в соответствующий набор инструкций процессора. Но вот беда, процесс может быть запущен только в одном режиме и переключаться между ними он не в состоянии, поэтому, как только ваше приложение попытается загрузить неуправляемую библиотеку, оно рухнет со страшными криками в виде BadImageFormatException.

Решается эта проблема весьма просто, достаточно это приложение скомпилировать под платформу x86, явно указав это в настройках проекта (установив Platform target в x86). Это явным образом скажет операционной системе, что это приложение нужно запускать в режиме совместимости и никаких ошибок во время выполнения вы больше не получите. Именно поэтому в Visual Studio 2010 изменены настройки по умолчанию у всех «управляемых» исполняемых файлов. Теперь, у всех приложений вместо Any CPU Target platform установлен как x86. Это не касается сборок (Assembly), у них в настройках по-прежнему используется Any CPU, но это и не важно, поскольку операционная система все равно отталкивается от информации в заголовке исполняемого файла.

64-х битная ОС и 64-х битная неуправляемая dll

С первого взгляда может показаться, что на 64-х разрядной операционной системе не может быть проблем с 64-х битными неуправляемыми dll, однако две бессонные ночи (*) показали, что это совсем не так.

Итак, давайте рассмотрим следующий сценарий: у нас есть сборка, скомпилированная под Any CPU, которая использует неуправляемую 64-х битную dll, и все это дело используется из powershell-а (рисунок 2).

Рисунок 2 – Архитектура приложения

С первого взгляда, в такой архитектуре нет ничего криминального, и действительно, так оно и было, пока мы не попытались запустить все это дело через нестандартный планировщик (**), который оказался 32-х разрядным приложением. Все дело в том, что при попытке запустить управляемое приложение, скомпилированное под Any CPU из 32-х битного приложения, работаюего в режиме WOW64, ваше приложение также будет запущено в этом же 32-х битном режиме (рисунок 3).

Рисунок 3 – Запуск PowerShell.exe из 32-х битного планировщика

Теперь мы получаем аналогичную проблему, но уже вывернутую на изнанку: мы получаем BadImageFormatException при попытке использовать неуправляемую 64-х битную dll из 32-х битного процесса на 64-х битной операционной системе! Звучит неправдоподобно, но это факт! Причем самое интересное, что существует 32-х битная версия PowerShell.exe, которая располагается C:\Windows\SysWOW64\WindowsPowerShell\v1.0, но вот «чистой» 64-х битной версии не существует.

Решение проблемы состоит в использовании дополнительного приложения, принудительно скомпилированного в режиме x64, которое будет запускаться из 32-х битного планировщика, и которое, в свою очередь, будет запускать PowerShell.exe в 64-х битном режиме (рисунок 4). Другим вариантом решения является использование утилиты CorFlags, которая может изменить информацию в заголовке исполняемого файла и заставить запускаться исполняемый файл в указанном формате. Однако эта славная утилита была найдена слишком поздно, и исправлять что-то на продакшне уже не было никакого желания.

Рисунок 4 – Запуск PowerShell.exe с помощью дополнительного приложения

Ну что ж, на сегодня все. Я надеюсь, что на практике вы не столкнетесь с подобными проблемами, а если и столкнетесь, то не будете под таким прессом времени и ответственности, под каким оказалась наша команда. Но, в любом случае, я надеюсь, что эта небольшая заметка сможет помочь вам решить проблемы запуска «управляемых» приложений под 64-х битными операционными системами, если такая проблема вдруг возникнет.

(*) Причина двух бессонных ночей была не только в этом, там получился целый ряд проблем, и эта – была лишь одной из них.

(**) Что это за планировщик и почему используется именно он, совершенно не важно, важно только то, что он оказался «чистым» 32-х битным приложением.

Windows x64 — Почему все ещё так много 32-разрядных программ?

Ваш компьютер, вероятнее всего, работает на 64-разрядной версии Windows. Но если открыть «Диспетчер задач», то Вы увидите, что большинство программ в Вашей системе все еще 32-разрядные. Действительно ли это проблема?

Есть много различий между 64-разрядными и 32-разрядными версиями Windows. 64-разрядные версии Windows могут выполнять 32-разрядное программное обеспечение, но 32-разрядные версии Windows не могут выполнить 64-разрядное программное обеспечение.

Как узнать разрядность программы?

Давайте воспользуемся диспетчером задач, чтобы увидеть, какие из ваших программ являются 64-разрядными, а какие 32-разрядными. Щелкните правой кнопкой мыши на панели задач и выберите пункт «Диспетчер задач» или нажмите комбинацию клавиш Ctrl + Shift + Esc, чтобы открыть его.

Посмотрите на столбец с названиями процессов. Если Вы будете использовать 64-разрядную версию Windows 8.1 или 8, то Вы увидите слово «(32-bit)» после каждого имени 32-разрядной версии программы. Если Вы будете использовать 64-разрядную версию Windows 7, то Вы увидите вместо этого «*32».

32-разрядные программы обычно устанавливаются в папку C:\Program Files (x86)\ на 64-разрядных версиях Windows, в то время как 64-разрядные программы обычно устанавливаются в папку C:\Program Files\.
Это — просто правило. Но ни кто не говорит, что нет другого правила, в котором запрещается устанавливать 64-разрядные программы в папку C:\Program Files (x86)\. Например, Steam — 32-разрядная программа, таким образом, она устанавливается в «C:\Program Files (x86)\» по умолчанию. Игры, которые Вы устанавливаете в Steam, установлены в папку C:\Program Files (x86)\Steam по умолчанию, в т.ч. даже 64-разрядные версии игр.

Если Вы сравните две различные папки Program Files, то Вы найдете, что большинство Ваших программ, вероятнее всего, установлены в папку C:\Program Files (x86). И, эти программы в большинстве своём являются 32-разрядными.

Работа 32-разрядного программного обеспечения на 64-разрядной операционной системе

На первый взгляд, это кажется ужасным, что большинство ваших программ Windows, не пользуются 64-битной архитектурой операционной системы. Вы можете подумать, что есть потери в производительности для запуска 32-разрядных программ в 64-разрядной операционной системы, но это не так.

Windows выполняет 32-разрядные программы через уровень совместимости WoW64 на 64-разрядных версиях Windows. Однако 64 -разрядные процессоры Intel и AMD обратно совместимы и могут напрямую выполнять 32-разрядное программное обеспечение. Все ваши 32-разрядные Windows-программы будут работать так же, как они работали бы на 32-разрядной версии Windows. Таким образом, нет никаких препятствий к выполнению этих программ на 64-разрядной операционной системе.

Даже если каждая программа, которую Вы используете, является все еще 32-разрядной, то Вы извлечете выгоду, потому что Ваша операционная система сама будет работать в 64-разрядном режиме. А, 64-разрядная версия Windows является более безопасной.

64-битные программы и 32-битные программы: что лучше?

32-битные программы запускаются без проблем на 64-битных версиях операционных систем Windows. Но было бы лучше, если бы все ваши программы были бы 64-битными?

Есть определенно преимущества у 64-битных программ. 32-разрядные программы могут использовать только 2 ГБ памяти, в то время как 64-битные программы могут использовать гораздо больше. Если программа, скорее всего, попала под атаку, дополнительные функции безопасности, применяемые к 64-битных программ, могут помочь. Google Chrome в настоящее время является 32-битным приложением даже на 64-битных версиях ОС Windows, но уже появилась 64-битная бета версия этой программы. И Google обещает, что 64-битная версия Chrome будет быстрее, более безопасной и более стабильной.

Некоторые программы предлагают 64-разрядные версии. Например: Photoshop, Itunes, Microsoft Office, и некоторые из самых популярных программ для Windows, и все они доступны в 64-битном виде. Последние игры тоже часто являются 64-разрядными, чтобы они могли использовать более 2 ГБ памяти.

Многие программы не сделали переход на 64-бита, и большинство никогда его не сделают. Вы все еще можете запускать сегодня большинство 32-битных программ Windows, даже те которые были выпущены десять лет назад, на 64-битной версии Windows, даже если их разработчики уже обновляют.

Разработчик, который хочет обеспечить 64-разрядную версию своей программы, должен выполнять много дополнительной работы. Он должен убедиться, что существующий код компилируется и правильно работает как 64-битное программное обеспечение. Он должен обеспечить и поддерживать две отдельные версии программы, так как пользователи под управлением 32-разрядной версии ОС Windows, не могут использовать 64-разрядную версию.

Давайте возьмем, в качестве примера программу Evernote для настольной версии Windows. Даже если они выпустили бы 64-разрядную версию Evernote, пользователи, вероятнее всего, не заметили бы разницы вообще. 32-разрядная программа может прекрасно работать и на 64-разрядной версии Windows, и если нет заметных преимуществ, то нет и смысла в 64-битной версии.

Где найти 64-разрядные приложения

Вы, как правило, не будете способны выбирать между 32-битной и 64-битной версий программного обеспечения. Например, при установке Itunes для Windows, веб-сайт компании Apple автоматически направляет вас к 32-разрядной или 64-разрядной версии установщика в зависимости от версии Windows. При установке Photoshop для Windows, как правило устанавливаются и 32-разрядные, и 64-разрядные исполняемые файлы. Photoshop автоматически выбирает из них. Иногда вы можете увидеть отдельные ссылки для загрузки 32-битных и 64-битных версий программ, но это не так распространено.

Важно не заниматься поиском 64-битных приложений, а найти приложения, которые работают хорошо для вас. Для большинства приложений, на самом деле не имеет значения 64-битная версия или 32-битная.

Легко задаться вопросом, почему так много приложений все еще 32-битные, когда вы открываете ваш менеджер задач. Но это не очень большая проблема и вот почему. Потому, что большинство приложений ни чего не выигрывают при переходе на 64-битные редакции версии программ. Даже если разработчики сделали всю работу и выпустили 64-битные версии всех маленьких настольных приложений и утилит, которые вы используете в Windows, то вы не смогли бы заметить разницу для большинства из них.

Что установить: Windows 32-bit или 64-bit?

Перед тем, как сравнивать 32-битную и 64-битную редакции Windows следует понять, что представляют из себя эти редакции, и какого их значение. Сначала расскажем о процессорах. Многие, возможно слышали о существовании 32-битных и 64-битных процессоров. Рассмотрим, что же означают эти биты.

Наверное не стоит говорить о том, что процессор – это достаточно сложное устройство. Он состоит из множества разных блоков, среди которых и кэш-память, и разные уровни, и блоки выбора и декодирования команд, блоки предсказывающие переходы, разные типы вычислительных блоков. В некоторых современных процессорах также имеются контроллеры памяти, контроллер шины PCI-Express и графическое ядро. В этой статье для нас важны вычислительные блоки.

Процессор может иметь разные типы таких блоков. Одни производят вычисления с целыми числами, другие — операции с вещественными числами или числами с плавающей запятой. Кроме того существуют блоки для т.н. сложных инструкций. В качестве примера рассмотрим блоки выполняющие вычисления с целыми числами или ALU. Во время работы эти блоки где-то должны хранить промежуточные данные. Для этих временных хранилищ были созданы регистры. От обычной памяти и кеш памяти их отличают прежде всего минимальные задержки и очень высокая скорость работы. Так вот эти самые регистры и скрывают главное отличие т.н. 32-битных и 64-битных процессоров. Рассмотрим это более подробно.

Так называемые 32-битные процессоры имеют 8 регистров общего назначения, объем которых составляет 32 бита. А 64-битные процессоры имеют в двое больше таких регистров, а объем их составляет 64 бита. Вот это и есть основное различие между 32-битными и 64-битными процессорами. Стоит сказать о том, что почти все современные процессоры являются 64-битными.

А теперь расскажем о том, для чего на практике нужны эти регистры. Если сказать обобщенно, то процессор на 64-бит в нормальном 64-битном режиме сможет работать с 64-битными числами не используя какие-либо ухищрения, как например, разбивку одной сложной операции на две. Кроме того таким образом могут быть объединены 2 простые операции над 32-битными числами в 1 сложную. Тем не менее не каждую операцию можно объединить с другой, но и это не мало.

Важно: производительность можно увеличить лишь работая с 64-битным наборам инструкций х86-64. Также следует сказать о том, что помимо блока вычислений с целыми числами ALU, процессор также имеет блок вычислений чисел с плавающей точкой или FPU. В нем содержатся более объемные 80-битные регистры и используются инструкции х87. Помимо этого процессор имеет другие блоки и регистры. Например, SSE-регистры. Их длина составляет 128 бит.


Мы помним о том, что есть 64-битный режим работы. Но есть и другие. 64-битный процессор имеет поддержку и так называемого режима совместимости, в котором дополнительные восемь регистров выключаются и поведение 64-хбитного процессора становится таким же как 32-битного. Это требуется прежде всего для того, чтобы обеспечить совместимость системного ПО и программ, не умеющих работать с 64-битным процессором. Почему он собственно и назван режимом совместимости.

Для того, чтобы процессор мог нормально работать в 64-битном режиме, потребуется 64-битная ОС и соответствующие драйвера. Если установлена 32-битная ОС, то процессор будет работать в режиме совместимости и вести себя как 32-битный процессор.

Важно: некоторые читатели могут вполне справедливо спросить о том, как 32-битные программы смогут работать в 64-битной ОС. Эту проблему удалось решить вполне логично: система имеет 2 набора системных библиотек для 64-битных и 32-битных приложений.

Но у разрядности регистров есть и более актуальная проблема. Дело в том, что ограничено адресное пространство для памяти. А попросту говоря, процессор способен адресовать лишь 4 Гб адресного пространства. Так ведь ноутбук и имеет 4Гб оперативной памяти, и системе должно быть видно все эти 4Гб. Но помимо оперативной памяти, есть и память видеокарты, буферы разных устройств и BIOS может для этого же видеоядра выделить еще какую-то память. В результате память, которая была доступна пользователю уменьшится 2.5 — 3.5 Гб. И это ограничение не зависит от операционной системы. Перейдем к более детальному рассмотрению этой проблемы.

Тут нет ничего сложного. Регистры хранят как данные, так и указатели адресов. В 32-битном процессоре объем этого регистра составляет 32 бита. Вот откуда появилось это ограничение в 4 Гб или 232 байт.

Подводя итог всего изложенного выше, стоит сказать, что любая 32-битная ОС не может работать используя все 4 Гб ОЗУ по той причине, что большинству системных устройств для работы требуется часть адресного пространства, а оно ограничено 4Гб. Поэтому системе приходится отбирать его у оперативной памяти. Неиспользованная оперативная память может быть использована в качестве временного диска, для этого потребуется утилита RAM Disk.

Важно: для 32-битных ОС создан механизм, позволяющий использовать адресное пространство более 4Гб. Это т.н. PAE (Physical Address Extension), в этом случае ОС может адресовать до 64 Гб памяти. Эту технологию с самого начала разрабатывали для серверных систем. Для того, чтобы она могла нормально работать требуются соответствующие исправленные драйвера. Так как таких рабочих драйверов почти нет, то эта технология даже на серверных ОС по умолчанию отключена. В обычных редакциях ОС Windows она также была отключена по умолчанию. И по той же причине. Сегодня есть специалисты, которые научились ее включать, система может видеть всю оперативную память, которая доступна ей, но происходят ошибки в самых разных местах. А их диагностика не так проста. Поэтому если вы хотите использовать более 3 — 4 Гб ОЗУ, то вам нужно установить 64-битную ОС.

Как можно видеть, в 64-битном режиме работы имеются следующие преимущества и недостатки:

  • 64-битная ОС работает со всем объемом ОЗУ;
  • Некоторые из операций на 64-битном процессоре могут быть выполнены намного быстрее;
  • Для 64-битных указателей требуется больше памяти, что делает объем занимаемой приложениями ОЗУ больше.

Как видите, не все так однозначно. Рассмотрим теперь как же это проявляется на практике.

Сравнение производительности 32-bit и 64-bit версий Windows

Сначала расскажем о том какая методика тестирования использовалась.

Измерения были проведены на ноутбуке Asus N61Vn имеющим четырехьядерный процессор Intel Core 2 Quad Q9000, использовалась видеокарта nVidia GeForce GT 240M с 1 Гб выделенной памяти. Важно заметить, что ноутбук имел 4 Гб ОЗУ DDR3-1066. При сравнении были использованы 32- и 64-битные версии Windows Vista SP2 с установленными последними обновлениями. Драйвера имели одинаковые версии, что позволило нивелировать разницу в производительности между различными версиями. По указанным выше причинам 32-битная версия Windows имела приблизительно 3Гб доступной оперативной памяти, а 64-битная редакция — примерно 4 Гб.

Важно также заметить то, что этот тест был проведен на Windows XP и Windows 7 на ноутбуке Acer Timeline 3810T с одноядерным процессором Intel Core 2 Duo SU3500 и 4Гб оперативной памяти, у которого были более ограниченные возможности. Результаты и в этих случаях не изменились и были приблизительно такие же.

Сравнение производительности для удобства мы разделили на 2 части:

  • 1. Сначала мы исследовали производительность обычных 32-битных программ на 32-битной и 64-битной версиях систем;
  • 2. Затем мы измеряли скорости работы 32-битной и 64-битной версий программ на соответствующих редакциях Windows.

Тестирование производительности прикладных 32-битных программ

Цель этого тестирования — определить увеличение производительности при переходе с 32-битной на 64-битную версию системы Windows. Данное исследование является актуальным, так как сегодня у многих игр и программ отсутствуют специальные оптимизированные 64-битные версии. Важно отметить и то, что 32-битная система может работать с 3 Гб памяти, а 64-битная версия — с 4 Гб.

Сравнить производительность помогли следующие приложения:

  • 3DMark03 3.6;
  • 3DMark05 1.3;
  • 3DMark06 1.1;
  • PCMark05 1.2.

Эти приложения были выбраны, так как они достаточно точно отражают реальную производительность большей части программ и игр. Если бы в данном исследовании были использованы различные прикладные программы, то методика исследования стала бы намного сложней. А процент погрешности измерений был бы увеличен из-за худшего повторения того или иного теста и ограничения точности в средствах измерения.

1. Итоги сравнения производительности в 3DMark03

Приложения были настроены по умолчанию. Разрешение экрана 1024 х768:

2. Результаты сравнения производительности в 3DMark05

Приложения были настроены по умолчанию. Разрешение экрана 1024 х768:

3. Результаты сравнения производительности в 3DMark06

Приложения были настроены по умолчанию. Разрешение экрана 1280 х720:

4. Результаты сравнения производительности в PCMark05

В этом тесте были проведены отдельные дополнительные тесты. Ниже представлены результаты каждого.

Результат общего исследования в PCMark05

Производительность процессора с тестовым пакетом PCMark05

Производительность памяти в рамках теста PCMark05

Виден результат полученный благодаря дополнительному гигабайту ОЗУ у 64-битной системы.

Производительность графики в тесте PCMark05

Результаты производительности винчестера в PCMark05

Итоги сравнения производительности обычных приложений

Результаты полученные после проведения данного исследования оказались весьма ожидаемыми. Из-за того, что был использован режим совместимости у 64-битной ОС при работе с обычными 32-битным приложениями производительность оказалась меньше.

В результате этого сравнения производительности также было выявлено, что реальную пользу 4 гигабайта ОЗУ в этом наборе приложений не приносят. Здесь необходимо подчеркнуть, что в действительности для тяжелых приложений, к которым относятся графические редакторы, системы автоматизированного проектирования (CAD) и другие, объем ОЗУ очень важен. В них дополнительные гигабайты ОЗУ действительно полезны.

Сравнение производительности 32- и 64-битных программ

Цель данного исследования — измерить увеличение производительности во время использования оптимизированных 64-битных приложений на 64-битной ОС.

Для сравнения производительности были также использованы программы:

  • Архиватор 7-Zip версии 4.65;
  • Тестовый пакет PCMark Vantage.

1. Тестирование при помощи архиватора 7-Zip

Здесь он используется как тестовое приложение, так как он имеется и в 32-битной и в 64-битной версиях, он может работать с многоядерными процессорами, он способен достаточно сильно нагружать процессор, в нем имеется набор встроенных средств позволяющих тестировать производительность. Во время тестирования размер словаря насчитывал 32 Мб.


А теперь посмотрим на результаты:

Как можно видеть показатели архиватора 64-битной оптимизированной версии на 64-битной ОС были лучше в сравнении с аналогичной 32-битной версией на 32-битной системе. Этого и следовало ожидать. Оптимизации смогли себя показать.

2. Тестирование при помощи тестового пакета PCMark Vantage

Существует как 32-битная, так и 64-битная версии тестового пакета PCMark Vantage. В этом тестовом пакете имеются разные тесты. Рассмотрим каждый из них.

Общий результат в тестовом пакете PCMark Vantage

Производительность ОЗУ в PCMark Vantage

Скорость воспроизведения видео и TV в PCMark Vantage

Производительность для игр

Производительность воспроизведения музыкальных файлов в PCMark Vantage

Сравнение производительности коммуникаций в PCMark Vantage

Сравнение производительности в офисных программах

Сравнение производительности жесткого диска

Как и 7-Zip, в целом 64-битный тестовый пакет PCMark Vantage показал большую производительность чем 32-битный на 32-битной ОС. Здесь важным моментом оказались оптимизации под 64-битные процессоры, и больше объема доступной памяти: 4 Гб у 64-битной системы и 3 у ее 32-битной версии.

Итог сравнения производительности 32-битной версии Windows с 64-битной

Пришло время подвести итог данного теста:

  • Наибольшее увеличение производительности в 64-битных версиях Windows XP, Vista, 7 наблюдалось в случае, когда были использованы оптимизированные 64-битные версии приложений и игр. Во время работы с обычными приложениями, без оптимизации под 64-битную версию производительность не увеличивается;
  • Многие программы и игры не смогли показать заметного роста производительности когда был увеличен объем доступной ОЗУ больше 3 Гб. Исключением можно назвать сложные программы, которые позволяют работать с видео, изображениями, системы проектирования и прочие. В дальнейшем этих приложений будет больше. Для таких программ использовать 64-битную систему будет весьма обоснованно.
  • Некоторые из приложений на 64-битной ОС показали нестабильную работу по разным причинам. Но этих приложений не так много.

В конце хочется отметить то, что вы сами выбираете версию Windows для своих нужд. И если это исследование смогло вам помочь, то мы будем только рады.

Поддержка 64-бит приложений x86 никогда не появится в Windows 10 ARM

ARM-версия Windows 10 вскоре получит новый набор инструментов SDK для Windows 10 ARM64, позволяющий разработчикам создавать родные 64-битные приложения для этой платформы. Но это не решит проблему отсутствия совместимости с существующими высокопроизводительными программами, которые ради безопасности или доступа к большему объёму оперативной памяти исполняются исключительно в режиме x86-64. Таковыми являются многие игры высокого класса, а также, например, некоторые приложения пакета Adobe Creative Cloud, недоступные в 32-битных версиях.

В беседе с ZDNet менеджер подразделения Windows Эрин Чапл (Erin Chapple) рассказала, что эта проблема, возможно, никогда не будет решена: «Реализация эмуляции x86-64 в дополнение к x86 требует вдвое больших инженерных трудозатрат. Кроме того, Windows поддерживает только уровень абстракции Windows on Windows (WOW) для 32-бит, а не для 64-бит приложений. Нам нужно будет добавить поддержку 64-битной версии Windows on Windows». Это будет совершенно новая работа, а не просто развитие существующей поддержки исполнения 32-бит приложений x86 на 64-бит Windows 10 ARM. Вдобавок конечная производительность будет куда менее предсказуемой.

«Технически это реализуемо, но существует ещё разумный компромисс между требуемыми трудозатратами и преимуществами, которые получит конечный пользователь. Когда мы посмотрели на статистику наиболее используемых Windows-приложений x86, мы обнаружили, что большинство из них имеют 32-бит версии. Многие приложения вообще выпускаются только в 32-бит версиях. Большинство 64-битных приложений — это игры, которые находятся за пределами целевой аудитории таких ноутбуков. Наконец, те приложения, которые являются изначально 64-битными, как правило, создаются с расчётом на очень мощные компьютеры для достижения максимальной производительности. В результате мы решили сосредоточить наши инженерные вложения на создании собственного ARM64 SDK, чтобы разработчики могли компилировать родные приложения для ARM-устройств Windows», — подчеркнула руководитель.

Эрин Чапл также прокомментировала сообщения о недостаточной производительности эмуляции x86 на платформе Windows 10 ARM: «Если программа использует жёсткий диск, графику или сеть, всё это выполняется на уровне ядра и работает напрямую, с максимальной производительностью. Если же приложение x86 слишком завязано на CPU, то для трансляции команд требуется больше ресурсов по сравнению с исполнением родного кода ARM. Многое зависит также от типа и назначения программы. Во время нашего внутреннего тестирования мы обнаружили, что производительность большинства x86-приложений, работающих в режиме эмуляции, вполне отвечает ожиданиям пользователей относительно отзывчивости».

Избежать эмуляции на новой платформе Windows 10 ARM до сих пор можно было только создав UWP-приложение для Microsoft Store. Разработчики могли перекомпилировать существующее настольное ПО, если оно использовало лишь функции WinRT API и Core-версии .NET. Если же они задействовали функции вроде WinForms, требующие полной версии .NET, оставалось полагаться только на эмуляцию 32-битного кода x86.

В будущем, если разработчикам понадобится 64-битная производительность традиционного ПО или исполнение родного кода ARM, в идеале им необходимо будет компилировать написанные на C++ программы напрямую при помощи SDK для Windows 10 ARM64. Microsoft планирует осуществить запуск этого набора инструментов во время мероприятия Build 2020 в мае.

Поначалу такие приложения нельзя будет публиковать в магазине Windows Store, так что они заработают только в Windows 10 Pro ARM, а не в Windows 10 S ARM. Будет ли SDK поддерживать функции вроде WinForms, которые требуют наличия настольной версии .NET? «Мы всё ещё работаем над нашими планами относительно развития ARM64 SDK, в том числе, обдумываем, какие версии .NET будут поддерживаться», — сказала госпожа Чаппл.

Любопытно, что и программы самой Microsoft доступны на ARM-платформе в разных версиях. Например, браузер Edge пока является 32-битным на Windows 10 ARM и исполняется без эмуляции, но участники программы Windows Insider уже могут тестировать 64-битную версию Edge (скомпилированную, очевидно, при помощи Windows ARM64 SDK).

В то же время Internet Explorer и Office остаются по-прежнему 32-бит x86-приложениями: оставлены они в таком виде ради совместимости с расширениями и дополнениями (тем более, что программы пакета Office, как правило, нетребовательны к производительности CPU). В общим и целом, пока платформа Windows 10 ARM призвана стать основой для создания доступных и максимально мобильных устройств с акцентом на время автономной работы и интегрированную поддержку LTE. Они не предназначены для прямой конкуренции в области производительности с 64-битными системами на базе чипов Intel или AMD.

Компьютерные сети

Многоуровневая архитектура Интернета

Урок 07. Проблемы выявления 64-битных ошибок

Существуют различные подходы к выявлению ошибок в программном коде. Рассмотрим основные методологии и их эффективность в выявлении 64-битных ошибок.

Самым старым, проверенным и надежным подходом к поиску дефектов является совместный обзор кода (англ. code review). Эта методика основана на совместном чтении кода с выполнением ряда правил и рекомендаций, хорошо описанных в книге Стива Макконнелла «Совершенный код» (Steve McConnell, «Code Complete»). К сожалению, эта практика неприменима для крупномасштабной проверки современных программных систем в силу их большого объема.

Обзор кода в данном случае скорее можно рассматривать как хороший способ обучения и защиты от 64-битных ошибок в новом разрабатываемом коде. Для выявления же уже имеющихся ошибок данный способ неприемлем из-за его стоимости. Вам придется совместно внимательно прочитать весь код программного проекта, чтобы обнаружить все 64-битные ошибки.

Статический анализ кода

На помощь разработчикам, которые осознают необходимость регулярного просмотра кода, но не имеют достаточного количества времени, приходят средства статического анализа кода. Их основной задачей является сокращение объема кода, требующего внимания человека, и тем самым сокращение времени его просмотра. К статическим анализаторам кода относится достаточно большой класс программ, реализованных для различных языков программирования и имеющих разнообразный набор функций, от простейшего контроля выравнивания кода, до сложного анализа потенциально опасных мест. Преимуществом статического анализа является его хорошая масштабируемость. С его помощью можно в разумные сроки проанализировать проект любого объема. А систематическое использование анализаторов позволяет выявлять многие ошибки еще на этапе написания кода.

Метод статического анализа является наиболее оптимальным решением для выявления 64-битных ошибок. В дальнейшем, рассматривая паттерны 64-битных ошибок, мы будем показывать, как данные ошибки можно диагностировать, используя статический анализатор Viva64, входящий в состав PVS-Studio. В следующем уроке вы также подробнее познакомитесь с методологией статического анализа и инструментом PVS-Studio.

Метод белого ящика

Под тестированием методом белого ящика будем понимать выполнение максимально доступного количества различных веток кода с использованием отладчика или иных средств. Чем большее покрытие кода было достигнуто, тем более полно выполнено тестирование. Под тестированием по методу белого ящика также иногда понимают простую отладку приложения с целью поиска известной ошибки. Полноценное тестирование методом белого ящика всего кода программ уже давно стало невозможным в силу огромного размера современных программ. Сейчас тестирование по методу белого ящика удобно применять на этапе, когда ошибка найдена, и необходимо понять причину ее возникновения. У тестирования методом белого ящика существуют оппоненты, отрицающие полезность отладки программ в реальном времени. Основной мотив заключается в том, что возможность наблюдать ход работы программы и при этом вносить изменения в ее состояние порождает недопустимый подход в программировании, основанный на большом количестве исправлений кода методом проб и ошибок. Мы не будем касаться данных споров, но заметим, что тестирование по методу белого ящика в любом случае очень дорогой способ повышения качества больших программных систем.

Читателю должно быть очевидно, что полная отладка приложения для выявления 64-битных ошибок также нереальна, как и полный обзор программного кода.

Дополнительно стоит заметить, что при отладке 64-битных приложений, обрабатывающих большие массивы данных, способ пошаговой отладки может стать неприменимым. Отладка таких приложений может занимать намного больше времени. Стоит заранее обдумать возможность использования систем протоколирования («логирования») для отладки приложений или предусмотреть иные методы.

Метод черного ящика (юнит-тесты)

Намного лучше себя зарекомендовал метод черного ящика. К этому типу тестирования можно отнести юнит-тестирование (unit tests). Основная идея метода заключается в написании набора тестов для отдельных модулей и функций, проверяющего все основные режимы их работы. Ряд источников относят юнит-тестирование к методу белого ящика, поскольку оно основывается на знании устройства программы. Мы придерживаемся позиции, что тестируемые функции и модули следует рассматривать как черные ящики, так как юнит-тесты не должны учитывать внутреннее устройство функции. Обоснованием этому может служить такая методология, когда тесты разрабатываются до начала написания самих функций, что способствует повышению контроля их функциональности с точки зрения спецификации.

Юнит-тестирование хорошо зарекомендовало себя как при разработке простых, так и сложных проектов. Одним из преимуществ юнит-тестирования является то, что легко можно проверить корректность вносимых в программу исправлений прямо в ходе разработки. Стараются делать так, чтобы все тесты проходили в течение нескольких минут, что позволяет разработчику, который внес изменения в код, сразу заметить ошибку и исправить ее. Если прогон всех тестов невозможен, то обычно длительные тесты выносят отдельно и запускают, например, ночью. Это также способствует оперативному обнаружению ошибок, по крайней мере, на следующее утро.

C использованием юнит-тестов для поиска 64-битных ошибок связан ряд неприятных моментов. Стремясь сократить время выполнения тестов, при их разработке стараются использовать небольшой объем вычислений и объем обрабатываемых данных. Например, разрабатывая тест на функцию поиска элемента в массиве, не имеет большого значения, будет она обрабатывать 100 элементов или 10 000 000. Сотни элементов будет достаточно, а вот по сравнению с обработкой 10 000 000 элементов скорость выполнения теста может быть существенно выше. Но если вы хотите разработать полноценные тесты, чтобы проверить эту функцию на 64-битной системе, вам потребуется обработать более 4 миллиардов элементов! Вам кажется, что если функция работает на 100 элементах, она будет работать и на миллиардах? Нет. Приведем пример.

Мой блог находят по следующим фразам

Уточнения, корректировки и обсуждения статьи «Урок 07. Проблемы выявления 64-битных ошибок» — под данным текстом, в комментариях.

Ответственность, за все изменения, внесённые в систему по советам данной статьи, Вы берёте на себя.

Илон Маск рекомендует:  Что такое код mssql_num_rows
Понравилась статья? Поделиться с друзьями:
Кодинг, CSS и SQL