MCP

воскресенье, 17 апреля 2016 г.

ZeroMQ vs NetMQ

Последнее время не спеша изучаю ZeroMQ, а так как пишу в основном на .NET, то решил сравнить производительность двух реализаций, "официальной" clrzmq4 (в nuget'е пакет называется ZeroMQ, и все примеры с сайта на нём), и альтернативный вариант NetMQ, написанный полностью на .NET и совместимый с ZeroMQ.

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

Для самого простого варианта я взял Publisher/Subscribe модель и начал закидывать сообщения по-кругу, и смотреть на результат. Результат оказался слегка неожиданным, но красноречивым. Не буду делать графики, ибо и без них всё понятно. Просто некоторые пункты:

  • clrzmq4/NetMQ одинаково быстры (около миллиона сообщений в секунду) при работе с массивами байт
  • Два паблишера на одного сабскрайбера (странный вариант, ну да ладно), гораздо быстрее работают у NetMQ 
  • При попытке работы со строками clrzmq4 начинает резко сливать производительность (в 3 раза). Судя по-всему, не очень удачная работа с маршаллингом
  • С clrzmq4 надо быть очень аккуратным, пропущенный Dispose даст прирост в скорости, но может вызвать неприятные ошибки
В общем, тестировать производительность дальше неинтересно, не думаю, что там есть какая-то волшебная разница на разных паттернах, с учётом того, что у NetMQ гораздо приятнее API, рекомендую рассматривать в качестве реализации API сразу же его и не париться с выбором.
NetMQ — быстрее и удобнее.

четверг, 7 апреля 2016 г.

Производительность SQL при поиске по ключу в зависимости от типа

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

Но вот тут у меня закралась мысль, а насколько эффективно SQL в дальнейшем работает с данными типами? И не будут ли голые инты быстрее во всяких селектах и джойнах, да так, что перекроют с лихвой все недостатки при вставке (ведь в основном все селектят, это обычно важнее, чем вставка).

Тестировать можно долго и по-разному, но для простоты, я ограничился следующими условиями:

  • Таблицы с Id и Value (чтобы совсем грустные не были
  • Id типов int, bigint и guid (т.е. 4, 8 и 16 байт, меньшие типы несерьёзно тестировать)
  • Id - кластерный индекс и первичный ключ
  • Заполнение по Identity и по рандому (чтобы проверить, влияет ли более разреженный индекс на результаты). Для гуидов идентити эмулировалось вручную, генерацией "правильных" данных 
  • Заранее вставил 1000000 записей в каждую таблицу
  • Селекчу много раз определённую запись (глупо, но SQL ведь особых чудес ловкости отваги проявить тут не сможет, впрочем, попробовал разные записи, результат похож)
В качестве подходящей незагруженной железяки (чтобы не влияли на результаты) оказался сервер с SSD, достаточным количеством памяти, но с SQL 2008. Не очень свежо, но не думаю, что что-то менялось на подобных запросах. Впрочем, позднее перетестирую, и если результаты изменятся — обновлю пост.

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


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

Но дальше я решил разнообразить тесты и сделать точно такие же таблицы, но без ключей (не повторять самостоятельно, опасно для жизни!). Результаты оказались слегка обескураживающими
Инт тут не просто в пролёте, он в почти в 3 раза медленнее гуида! А бигинт самый быстрый (что, в принципе не так уж и странно, но не в случае такого провала с интом).
Вначале я думал, что табличке с интами не повезло и она нарвалась на длинный фулскан, пробовал селектить разные записи — результат идентичный. В чём дело, я не понимаю. Возможно проблемы SQL сервера, а возможно так и задумано, тут я не специалист. В общем, надо доисследовать, но ситуация очень неординарная. Бигинты круче интов в несколько раз...

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


Тут всё просто и логично, снос кластерного индекса экономит 4-5 мегабайт на миллионе записей, бигинт больше инта где-то на 4 мегабайта, гуид больше бигинта на 8-9 мегабайт в зависимости от наличия/отсутствия индекса.

Update: Обновил SQL Server с 2008 до 2014. Результаты: Поиск по индексу стал где-то на 40% быстрее (смысл обновляться оказывается имеется!), Поиск по таблицам без первичного ключа: с интами ничего не изменилось, гуиды стали быстрее на 30%, т.. практически сравнялись с бигнитами. Т.е. проблемы те же самые на месте, но гуиды стали ещё более привлекательнее. Картинка с данными:

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

среда, 6 апреля 2016 г.

Windows Update ошибка 800F0922

Собственно, данный пост на случай, если его нагуглят, ибо гугление ошибок с виндовым апдейтом — самое милое дело. Других сведений про источник проблемы обычно нет.
Итак, я долго возился с тем, что у меня не ставились некоторые обновления. Занимался уже делением пополам и установкой того, что ставится (ибо, если не ставится одно, откатываются все пакетом, ибо транзакционность). Но на днях решил разобраться, в чём же причина.
Собственно, т.к. не ставилась куча апдейтов, код конкретного не привожу, но ошибка была с кодом 800F0922, и выглядела примерно так

Гуглёж по коду выдал кучу безумных рекомендаций вида — удалить драйвер Cisco VPN или увеличить служебный раздел System Reserved. А также стандартные пляски с бубном вида sfc /scannow и сброса состояния Windows Update. Но первые причины явно были не мои, а вторые помогают только, когда действительно сломано всё. У меня же были проблемы только с частью апдейтов.

В общем, я пошёл копать в логи, которые у апдейтов находятся в C:\Windows\Logs\CBS\CBS.log на предмет, того, что же там не так. А не так там оказалась подобная строчка (хана дизайну блога, ну да ладно):

2016-04-05 10:03:35, Error                 CSI    00000001 (F) Logged @2016/4/5:07:03:35.059 : [ml:262{131},l:260{130}]"events installer: online=1, install=1, component=wow64_Microsoft-Windows-Win32k_31bf3856ad364e35_6.2.9200.17461_neutral_release__."
[gle=0x80004005]
2016-04-05 10:03:35, Error                 CSI    00000002 (F) Logged @2016/4/5:07:03:35.090 : [ml:240{120},l:238{119}]"EventAITrace:Provider Microsoft-Windows-Win32k is already installed with GUID {e7ef96be-969f-414f-97d7-3ddb7b558ccc}.

"
[gle=0x80004005]


2016-04-05 10:03:35, Error                 CSI    00000003 (F) Logged @2016/4/5:07:03:35.090 : [ml:168{84},l:166{83}]"WmiCmiPlugin manproc.cpp(683): InstrumentationManifestAssert failed. HR=0x80073aa2."
[gle=0x80004005]


2016-04-05 10:03:35, Error                 CSI    00000004 (F) Logged @2016/4/5:07:03:35.090 : [ml:166{83},l:164{82}]"WmiCmiPlugin eventloghandler.cpp(192): ProcessEventsInstall failed. HR=0x80073aa2."
[gle=0x80004005]


2016-04-05 10:03:35, Error                 CSI    00000005 (F) Logged @2016/4/5:07:03:35.090 : [ml:170{85},l:168{84}]"WmiCmiPlugin eventloghandler.cpp(212): EventLogHandlerInstall failed. HR=0x80073aa2."
[gle=0x80004005]


2016-04-05 10:03:35, Error                 CSI    00000006@2016/4/5:07:03:35.090 (F) CMIADAPTER: Inner Error Message from AI HRESULT = HRESULT_FROM_WIN32(15010)
 [
[22]"Configuration error.

"
]

аКлючевое в этом: EventAITrace:Provider Microsoft-Windows-Win32k is already installed with GUID {e7ef96be-969f-414f-97d7-3ddb7b558ccc}, т.е. в переводе на русский, уже есть источник журнала событий, а его опять пытаются сделать. Почему бы не успокоиться, я не знаю. Но решение тут банальное:

  • идём в реестр в ветку HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\WINEVT\Publishers\{e7ef96be-969f-414f-97d7-3ddb7b558ccc}
  • Экспортируем её на всякий случай
  • Удаляем
  • Перегружаемся (это важно)
  • Пробуем установить апдейт заново
И чудо! всё заработало. Все апдейты стали снова ставиться без проблем.
Это, естественно, не единственный вариант источника проблемы, но, может быть в вашем случае он поможет.