Рубрика «Блог компании Инфопульс Украина»

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

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

Итак, что же произошло.
Читать полностью »

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

Случалось ли Вам оказаться в ситуации, когда необходимо запустить какую-то программу, но Вы не совсем уверены в источнике её происхождения? Или другой пример — необходимость проверить что-то на «чистой» версии Windows. Во всех подобных случаях раньше был только один выход — установить ОС на отдельную физическую или виртуальную машину и провести нужный эксперимент. Но это больше не так.

Microsoft разработал новый механизм под названием Песочница (eng. Windows Sandbox). Это изолированное временное окружение, в котором Вы можете запускать подозрительное программное обеспечение без риска навредить своему ПК. Любое ПО, установленное в Песочнице, остаётся только в Песочнице и не может взаимодействовать с основной ОС. Как только Вы закрываете Песочницу — всё её содержимое безвозвратно уничтожается.

Вот основные особенности Песочницы:

  • Это часть ОС Windows. Если у Вас Windows 10 Pro или Enterprise, то Вы уже можете начать ею пользоваться.
  • С чистого листа. При каждом запуске Песочницы Вы получаете одно и то же, чистое, неизменное окружение. В точности такое, какой была Ваша ОС сразу после её установки.
  • Никаких следов. При закрытии Песочницы уничтожаются все установленные в ней приложения, все созданные там файлы. Закрыли Песочницу — не осталось никаких следов её существования.
  • Безопасность. Используется аппаратная виртуализация, которая использует гипервизор для запуска отдельного ядра ОС и изолирует его от Вашей основной ОС
  • Эффективность. Используется интегрированный планировщик задач, умное управление памятью, виртуальный GPU.

Читать полностью »

Резервуарная выборка (eng. «reservoir sampling») — это простой и эффективный алгоритм случайной выборки некоторого количества элементов из имеющегося вектора большого и/или неизвестного заранее размера. Я не нашел об этом алгоритме ни одной статьи на Хабре и поэтому решил написать её сам.

Итак, о чём же идёт речь. Выбрать один случайный элемент из вектора — это элементарная задача:

auto result = vect[rand() % vect.size()]; // С++

Задача «вернуть K случайных элементов из вектора размером N» уже хитрее. Здесь уже можно ошибиться — например, взять K первых элементов (это нарушит требование случайности) или взять каждый из элементов с вероятностью K/N (это нарушит требование взять ровно K элементов). Кроме того, можно реализовать и формально корректное, но крайне неэффективное решение «перемешать случайно все элементы и взять K первых». И всё становится ещё интереснее, если добавить условие того, что N — число очень большое (нам не хватит памяти сохранить все N элементов) и/или не известно заранее. Для примера представим себе, что у нас есть какой-то внешний сервис, присылающий нам элементы по одному. Мы не знаем сколько их придёт всего и не можем сохранить их все, но хотим в любой момент времени иметь набор из ровно K случайно выбранных элементов из уже полученных.

Алгоритм резервуарной выборки позволяет решить эту задачу за O(N) шагов и O(K) памяти. При этом не требуется знать N заранее, а условие случайности выборки ровно K элементов будет чётко соблюдено.
Читать полностью »

Смотрел я тут на днях выступление Kate Gregory на конференции Pacific++ 2018.

Видео выступления

Кейт — хороший программист и отличный спикер. Сам доклад поднимает много интересного о программировании на С++ и программировании вообще (стоит посмотреть). Но больше всего меня зацепила одна высказанная ею (буквально вскользь) мысль. Кейт удалось очень кратко и по делу обозначить мотивацию программистов. Звучала она так: «Программист во время работы стремится максимизировать своё счастье». Это звучит банально, но ведь так оно и есть.

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

Сразу хочу вынести за скобки вопросы оплаты труда, условий работы, начальства, коллектива и прочего. Если вы работаете там, где работаете — то всё это вас примерно устраивает. Давайте сфокусируемся на том, что делает нас счастливыми и несчастными при непосредственной работе над кодом.
Читать полностью »

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

Когда речь заходить о тестировании производительности — в первую очередь все думают о JMeter’е — он бесспорно остается самым известным инструментом с самым большим количеством плагинов. Мне же JMeter никогда не нравился из-за неочевидного интерфейса и высокого порога вхождения, как только возникает необходимость протестировать не Hello World приложение.

И вот, окрыленный успехом проведения тестирования в двух различных проектах, решил поделится информацией об относительно простом и удобном софте — Locust

Для тех, кому лень идти под кат, записал видео:

Читать полностью »

Некоторые люди как-то неправильно поняли WebAssembly. Есть те, кто считает, что раз браузеры уже поддерживают выполнение WebAssembly (ещё с 2017 года), значит всё уже готово. Даже и близко ещё нет, готов лишь MVP (минимально жизнеспособный продукт). Я могу предположить откуда произрастает корень этого заблуждения: после релиза MVP его разработчики пообещали поддерживать обратную совместимость на уровне «любой написанный сейчас код будет работать и в будущем». Но это ведь не значит, что разработка WebAssembly закончена, совсем нет! Множество фич разрабатывается прямо сейчас и планируется к разработке в ближайшем будущем. И когда они будут реализованы — всё очень сильно изменится.

Все эти фичи можно попробовать представить себе в виде дерева навыков в какой-нибудь игре. У нас есть пару «базовых» (уже реализованные фичи) и целое дерево со множеством веток и листьев, которые будут со временем открываться, давая нам всё больше и больше могущества.
image
Давайте посмотрим на то, что у нас уже есть сейчас и что нам ещё предстоит открыть.
(Под катом много картинок, трафик)
Читать полностью »

Не так давно мимо нас пробегала неплохая статья об ужасном состоянии производительности современного ПО (оригинал на английском, перевод на Хабре). Эта статья напомнила мне об одном антипаттерне кода, который встречается весьма часто и в общем кое-как работает, но приводит к небольшим потерям производительности то тут, то там. Ну, знаете, мелочь, пофиксить которую руки никак не дойдут. Беда лишь в том, что десяток таких «мелочей», разбросанных в разных местах кода начинают приводить к проблемам типа «вроде у меня последний Intel Core i7, а прокрутка дёргается».

Как правильно и неправильно спать - 1Я говорю о неверном использовании функции Sleep (регистр может отличаться в зависимости от языка программирования и платформы). Итак, что же такое Sleep? Документация отвечает на этот вопрос предельно просто: это пауза в выполнении текущего потока на указанное количество миллисекунд. Нельзя не отметить эстетическую красоту прототипа данной функции:

void Sleep(DWORD dwMilliseconds);

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

Ещё большим уважением проникаешься к этой функции, когда читаешь, как она работает

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

Что же могло пойти не так? То, что программисты используют эту замечательную функцию не для того, для чего она предназначена.
Читать полностью »

Один из пользователей компилятора Visual C++ привёл следующий пример кода и спросил, почему его цикл с условием выполняется бесконечно, хотя в какой-то момент условие должно перестать выполняться и цикл должен закончиться:

#include <windows.h>

int x = 0, y = 1;
int* ptr;

DWORD CALLBACK ThreadProc(void*)
{
  Sleep(1000);
  ptr = &y;
  return 0;
}

int main(int, char**)
{
 ptr = &x; // starts out pointing to x

 DWORD id;
 HANDLE hThread = CreateThread(nullptr, 0, ThreadProc, 0, &id);

 // Ждём, пока другой поток изменит значение по указателю ptr
 // на некоторое ненулевое число
 while (*ptr == 0) { }

 return 0;
}

Читать полностью »

Мой любимый файл в кодовой базе Chromium - 1Код Хромиума весьма обширен, там каждому найдётся что-то по вкусу. А я вот решил рассказать о своём любимом файле в нём (а у вас есть такой?). Этот файл отражает всё: боль, разочарование, надежду, упорство, силу воли, ответственность за чужие провалы и самопожертвование. Я иногда читаю его и плачу и проникаюсь пониманием, какая же огромная часть айсберга скрыта под водой. Это, в общем, даже не файл с кодом. Это файл с конфигом, описывающим баги видеокарт, которые Хромиуму приходится обходить для нормального отображения своих страниц на разных платформах. Вот он: https://cs.chromium.org/chromium/src/gpu/config/gpu_driver_bug_list.json

О чём вообще идёт речь? Давайте вспомним, как работает браузер: вы набираете какой-то адрес в адресной строке, браузер загружает контент и отображает его. Чуть детальнее об этом рассказывает хорошая статья «What happens when you type google.com into your browser and press enter?» (и сразу несколько её переводов на Хабре). В ней одним из последних пунктов упоминается, мол, «а теперь, когда всё готово, отрисовываем картинку на экране». Ага, вот так берём и отрисовываем, конечно.
Читать полностью »

Ну или начните делать это правильно.

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

«Нам нужно реализовать решение {Х}, несмотря даже на то, что есть значительно более простое и подходящее нам сейчас решение {Y}, ведь когда в будущем произойдёт {Z}, то {X} сработает гораздо лучше, чем {Y}».

При этом точной информации о вероятности наступления события {Z} нет и быть не может.

Вот пара примеров:

  • Нам нужно использовать kubernetes и docker! Да, с текущей нагрузкой отлично справляется один сервер и его легко настроить и поддерживать, но ведь когда нам нужно будет дюжина серверов — будет легче их разворачивать с kubernetes и docker.
  • Нам нужна архитектура распределенной обработки данных! Да, пока со всем справляется один средненький ПК, но когда у нас будет решение промышленного уровня и заказчики потребуют аптайм в пять девяток после запятой в SLA — мы будем к этому готовы.
  • Нам нужно нанять команду разработчиков и создать сайт с нуля, не смотря на то, что значительно быстрее было бы развернуть что-то на базе wordpress, ведь когда у нас будет в 100 раз больше клиентов, чем сейчас, то wordpress станет не так удобен.
  • Нам нужно использовать наследование вместо композиции, ведь через 5 лет кодовая база разрастётся так, что без этого будет никак.
  • Нам нужно написать вот этот код на С++, не смотря на то, что на Python это будет в разы быстрее, ведь спустя годы он будет обрабатывать терабайты данных и Python может здесь не справится.

Недавно я писал статью о воображаемых проблемах — тех, решением которых люди развлекают себя, ведь их решать интереснее, чем реальные. Сюда же можно отнести и вот эти попытки предвидеть будущее. Даже можно сказать больше — это любимая воображаемая проблема большинства маленьких начинающих компаний.
Читать полностью »