https://yourcmc.ru/wiki/%D0%A1%D0%BB%D1%83%D0%B6%D0%B5%D0%B1%D0%BD%D0%B0%D1%8F:WikilogYourcmcWiki - Викилоги [ru]Читать последние сообщения на этом канале.https://yourcmc.ru/wiki/configs/favicons/custiswiki.icohttps://yourcmc.ru/wiki/configs/logos/mewiki-logo.png2024-03-14T10:56:33ZСодержимое доступно по лицензии <a class="external" rel="nofollow" href="http://creativecommons.org/licenses/by-sa/3.0/">CC-BY-SA</a> (если не указано иное).MediaWikihttps://yourcmc.ru/wiki/%D0%91%D0%BB%D0%BE%D0%B3:%D0%92%D0%B8%D1%82%D0%B0%D0%BB%D0%B8%D0%B9_%D0%A4%D0%B8%D0%BB%D0%B8%D0%BF%D0%BF%D0%BE%D0%B2/2024-01-22_%D0%9A%D0%B0%D0%BA_%D1%87%D1%83%D1%87%D1%83%D1%82%D1%8C_%D0%BF%D0%B5%D1%80%D0%B5%D0%BD%D0%B0%D0%B7%D0%BD%D0%B0%D1%87%D0%B8%D1%82%D1%8C_%D0%BA%D0%BB%D0%B0%D0%B2%D0%B8%D1%88%D0%B8_%D0%BD%D0%B0_Xiaomi_Mi_NotebookВиталий Филиппов — 2024-01-22 Как чучуть переназначить клавиши на Xiaomi Mi NotebookVitaliyFilippovhttps://yourcmc.ru/wiki/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:VitaliyFilippov2024-03-14T10:56:33Z2024-03-14T10:56:33Z<p>На Xiaomi Mi Notebook клавиатура отличная, почти идеальная.
</p><p>Есть вертикальный ряд кнопок home/end/pageup/pagedown, ход клавиш приятный, стрелочки полноразмерные.
</p><p>Единственное извращение - в углу клавиатуры стоит уникальная кнопка, которая ни за что не отвечает - по задумке ты на неё должен назначить что-то своё, Delete сдвинут влево, а Insert находится на Fn+F12. Ну и ряд вертикальный хочется home/pageup/pagedown/end, а не home/end/pageup/pagedown.
</p><p>Но всё это очень легко поправимо.
</p>
<pre>
# remap del -> ins
setkeycodes e053 110
# remap xiaomi key -> del
setkeycodes e072 111
# remap home end pgup pgdown -> home pgup pgdown end
setkeycodes e04f 104
setkeycodes e049 109
setkeycodes e051 107
</pre>
<p>И всё, каеф.
</p>
https://yourcmc.ru/wiki/%D0%91%D0%BB%D0%BE%D0%B3:%D0%92%D0%B8%D1%82%D0%B0%D0%BB%D0%B8%D0%B9_%D0%A4%D0%B8%D0%BB%D0%B8%D0%BF%D0%BF%D0%BE%D0%B2/2021-06-09_Blender,_OpenCL_%D0%B8_Radeon_ProRenderВиталий Филиппов — 2021-06-09 Blender, OpenCL и Radeon ProRenderVitaliyFilippovhttps://yourcmc.ru/wiki/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:VitaliyFilippov2021-06-09T08:54:42Z2021-06-09T21:53:07Z<p>Есть у меня такая традиция — раз примерно в год с блендером и каким-нибудь радеоном трахаться.
</p><p>В этот раз меня, в принципе, ждал успех. Получилось, во-первых, завести Cycles на OpenCL с Radeon RX 5500M (Navi 14) под Linux-ом, а во-вторых, даже получить расчётные показатели производительности! Расчётные — это немного быстрее нивидии GTX 1660 Ti и примерно на уровне GTX 1080 (да, она быстрее 1660), именно так, как и заявляется про данный GPU.
</p><p>Бонусом завёлся и Radeon ProRender, но на конкретном демо-файле толку от него оказалось мало.
</p><p>Итак, что я сделал…
</p><p>Есть у меня такая традиция — раз примерно в год с блендером и каким-нибудь радеоном трахаться.
</p><p>В этот раз меня, в принципе, ждал успех. Получилось, во-первых, завести Cycles на OpenCL с Radeon RX 5500M (Navi 14) под Linux-ом, а во-вторых, даже получить расчётные показатели производительности! Расчётные — это немного быстрее нивидии GTX 1660 Ti и примерно на уровне GTX 1080 (да, она быстрее 1660), именно так, как и заявляется про данный GPU.
</p><p>Бонусом завёлся и Radeon ProRender, но на конкретном демо-файле толку от него оказалось мало.
</p><p>Итак, что я сделал…
</p>
<h4><span class="mw-headline" id=".D0.A1.D0.BD.D0.B0.D1.87.D0.B0.D0.BB.D0.B0_.D0.BF.D1.80.D0.BE.D1.82.D0.B5.D1.81.D1.82.D0.B8.D1.80.D0.BE.D0.B2.D0.B0.D0.BB_Mesa_.2B_libclc">Сначала протестировал Mesa + libclc</span></h4>
<p>Чтобы Blender вообще увидел Mesa-девайс, нужно его запускать с <tt>CYCLES_OPENCL_TEST=1 blender</tt>.
</p><p>Далее обнаруживается, что Mesa до сих пор показывает версию OpenCL 1.1, потому что (лол) у них не реализована функция printf. Всё остальное реализовано (лол). Проблему можно обойти, запуская Blender с переменными окружения <tt>CLOVER_PLATFORM_VERSION_OVERRIDE=1.2 CLOVER_DEVICE_VERSION_OVERRIDE=1.2 CLOVER_DEVICE_CLC_VERSION_OVERRIDE=1.2 CYCLES_OPENCL_TEST=1 blender</tt>.
</p><p>И, наконец, выясняется, что на новые радеоны нет libclc, что выражается отсутствием файла <tt>/usr/lib/clc/gfx1012-amdgcn-mesa-mesa3d.bc</tt>. Я попробовал вместо него подложить другой, от tahiti, ничем хорошим это не увенчалось. Рендер запустился, но рендерил белый шум вместо картинки. На встроенный Renoir, кстати, тоже libclc нет, там нужен файл <tt>gfx902-amdgcn-mesa-mesa3d.bc</tt>.
</p><p>На этом эксперименты с Mesa завершились.
</p>
<h4><span class="mw-headline" id=".D0.9F.D0.BE.D1.82.D0.BE.D0.BC_.D1.80.D0.B5.D1.88.D0.B8.D0.BB_.D0.BF.D0.BE.D0.BF.D1.80.D0.BE.D0.B1.D0.BE.D0.B2.D0.B0.D1.82.D1.8C_.D0.B7.D0.B0.D0.BA.D1.80.D1.8B.D1.82.D1.8B.D0.B9_.D0.B4.D1.80.D0.B0.D0.B9.D0.B2.D0.B5.D1.80">Потом решил попробовать закрытый драйвер</span></h4>
<p>К счастью, выяснилось, что у AMD всё достаточно хорошо и ядерная часть закрытого и открытого драйверов совпадает, поэтому OpenCL-ные драйвера можно пробовать запускать, не ставя никаких дополнительных модулей ядра и не переходя на закрытый драйвер для графики
</p><p>Скачал драйвер AMDGPU-Pro 20.40 и поставил пакеты opencl-amdgpu-pro-comgr, opencl-amdgpu-pro-icd, ocl-icd-libopencl1-amdgpu-pro, ну и почти пустые amdgpu-core и amdgpu-pro-core, требующиеся по зависимостям.
</p><p>Всё брал для Ubuntu 20 — вообще я юзаю Debian Sid, но он достаточно похож на убунту, чтобы всё завелось.
</p><p>Проверил, как рекомендовали в интернете, файлик /etc/ld.so.conf.d/10-amdgpu-pro.conf на предмет наличия строк <tt>/opt/amdgpu-pro/lib/x86_64-linux-gnu</tt> и <tt>/opt/amdgpu-pro/lib/i386-linux-gnu</tt> и выполнил sudo ldconfig.
</p><p>На этом этапе у меня уже завёлся OpenCL 2.0 (появились девайсы в clinfo) и Blender их увидел. И даже тестовая сценка, которая валялась где-то под рукой (не с сайта блендера), успешно отрендерилась.
</p><p>Далее я скачал с сайта блендера Barcelona Pavillion и решил проверить рендер на нём. Увы, нет — на нём рендер стал падать.
</p>
<h4><span class="mw-headline" id=".D0.94.D0.B0.D0.BB.D0.B5.D0.B5_.D1.80.D0.B5.D1.88.D0.B8.D0.BB_.D0.BF.D0.BE.D0.BF.D1.80.D0.BE.D0.B1.D0.BE.D0.B2.D0.B0.D1.82.D1.8C_.D0.B2.D0.B5.D1.80.D1.81.D0.B8.D1.8E_.D0.B7.D0.B0.D0.BA.D1.80.D1.8B.D1.82.D0.BE.D0.B3.D0.BE_.D0.B4.D1.80.D0.B0.D0.B9.D0.B2.D0.B5.D1.80.D0.B0_20.50.2C_.D0.B8.D0.B1.D0.BE_20.40.C2.A0.E2.80.94_.D1.8F.D0.B2.D0.BD.D0.BE_.D0.BD.D0.B5_.D0.BF.D0.BE.D1.81.D0.BB.D0.B5.D0.B4.D0.BD.D1.8F.D1.8F">Далее решил попробовать версию закрытого драйвера 20.50, ибо 20.40 — явно не последняя</span></h4>
<p>…и обнаружил, что в нём изменился состав пакетов.
</p><p>Но процедуре установки «только OpenCL» это не помешало, только устанавливаемых пакетов стало больше: comgr-amdgpu-pro, hsa-runtime-rocr-amdgpu, hsakmt-roct-amdgpu, ocl-icd-libopencl1-amdgpu-pro, opencl-rocr-amdgpu-pro плюс требующиеся по зависимостям libdrm-amdgpu-amdgpu1, libdrm-amdgpu-common, libdrm2-amdgpu и те же amdgpu-core с amdgpu-pro-core.
</p><p>libdrm-* на самом деле не нужны, их приходится ставить только из-за зависимостей. Но вреда они не несут, так что можно ставить смело. Хотя на первом заходе я ещё поизвращался и поправил зависимости в deb пакете hsakmt-roct-amdgpu, убрав оттуда этот libdrm, перед установкой.
</p><p>После установки clinfo показало отсутствие девайсов в системе, однако, через strace стало понятно, что оно обращается к /dev/kfd, а /dev/kfd по дефолту доступно только группе render. Поэтому пришлось сделать <tt>adduser me render</tt> и добавить себя в группу, после чего перелогиниться.
</p><p>clinfo снова показал девайсы, а Blender стал успешно рендерить Barcelona Pavillion… но стал зависать на рендере тестовой сценки, которая на 20.40 успешно рендерилась.
</p><p>Здесь я уже замерил рендер Barcelona Pavillion-а — получилось 16:40 на GPU и примерно 8:50 на CPU+GPU (CPU Ryzen 4800 HS). Не очень хороший результат, прямо скажем.
</p>
<h4><span class="mw-headline" id=".D0.A0.D0.B5.D1.88.D0.B8.D0.BB_.D0.BF.D0.BE.D0.BF.D1.80.D0.BE.D0.B1.D0.BE.D0.B2.D0.B0.D1.82.D1.8C_.D1.81.D0.BD.D0.BE.D0.B2.D0.B0_.D0.BE.D0.B1.D0.BD.D0.BE.D0.B2.D0.B8.D1.82.D1.8C.D1.81.D1.8F">Решил попробовать снова обновиться</span></h4>
<p>Поискал получше и обнаружил, что последняя версия драйвера на самом деле 21.10, а не 20.50.
</p><p>А кроме того, всё это происходило на ядре 5.8, а в дебиане уже было в наличии как минимум 5.10.
</p><p>ОК. Скачал 21.10, провёл ту же процедуру установки пакетов. К счастью, в 21.10 пакеты от 20.50 уже не отличаются. Установил 5.10-е ядро.
</p><p>Перезагрузился и… у меня вообще перестала нормально работать графическая среда. X-ы стали виснуть, в dmesg появились сообщения о GPU reset и всё такое прочее. Причём OpenCL-драйвер тут был никак не виноват, это были просто регрессии драйвера amdgpu в более новом ядре.
</p><p>Что ж, пришлось пробовать ставить модуль ядра из комплекта поставки AMDGPU-Pro… Модуль, как я уже сказал, там тот же самый открытый, что и в обычном ядре — просто версия, видимо, поставляется сразу более новая.
</p><p>Ну ок. Ставим заголовки ядра (linux-headers-5.10.0-7-amd64), сам dkms и пакеты amdgpu-dkms-firmware и amdgpu-dkms… и обламываемся, потому что модуль из AMDGPU-Pro отказывается собираться с ядром 5.10.
</p><p>К счастью, мы всё-таки не лыком шиты и тривиальные ошибки вида «добавился/удалился параметр функции» в модуле ядра поправить можем. Ошибок оказывается немного — всего 3 — и после вот таких вот исправлений: <a href="https://yourcmc.ru/wiki/images/0/0b/Amdgpu-dkms-5.10.diff" class="internal" title="Amdgpu-dkms-5.10.diff">Media:Amdgpu-dkms-5.10.diff</a> — модуль успешно собирается и устанавливается.
</p><p>Вуаля! После перезагрузки графика снова работает, а Blender наконец-то <b>работает стабильно</b>. Не виснет и не падает.
</p>
<h4><span class="mw-headline" id=".D0.9D.D0.B0.D1.81.D1.82.D1.83.D0.BF.D0.B8.D0.BB.D0.BE_.D0.B2.D1.80.D0.B5.D0.BC.D1.8F_.D0.BF.D1.80.D0.BE.D0.B3.D0.BD.D0.B0.D1.82.D1.8C_.D1.82.D0.B5.D1.81.D1.82.28.D1.8B.29">Наступило время прогнать тест(ы)</span></h4>
<p>Снова рендерим Barcelona Pavillion:
</p>
<ul><li> Cycles «Supported»
<ul><li> GPU only (192x192 tile) — 10:23</li>
<li> CPU+GPU (192x192 tile) — 06:22</li></ul></li>
<li> Cycles «Experimental»
<ul><li> GPU only (192x192 tile) — 09:32</li>
<li> CPU+GPU (128x128 tile) — 05:48</li></ul></li></ul>
<p>И это уже таки можно считать успехом, ибо вот тут на похорониксе: <a rel="nofollow" class="external free" href="https://www.phoronix.com/scan.php?page=article&item=blender-281-optix&num=3">https://www.phoronix.com/scan.php?page=article&item=blender-281-optix&num=3</a> - есть данные по рендеру на различных Nvidia-х. GTX 1660 Super выдал 628 секунд, GTX 1080 успел за 565, а у нас 572. Вполне неплохо, Radeon RX 5500M и считается примерным аналогом GTX 1660 / 1660 Ti, даже по числу транзисторов. Ну и то, что оно в принципе стабильно работает, само по себе уже успех. До RTX с OptiX, понятно, не дотягивает, но тот RTX стоит как весь этот ноутбук, так что по Сеньке шапка.
</p><p>Вдогонку:
</p>
<ul><li> Classroom (GPU only) — 5:04, для сравнения GTX 1660 Super — 5:26</li>
<li> BMW27 (GPU only) — тут похуже, 2:21, для сравнения GTX 1660 Super — 1:24, GTX 1650 — 2:24</li></ul>
<h4><span class="mw-headline" id=".D0.9E.D1.82.D0.B4.D0.B5.D0.BB.D1.8C.D0.BD.D0.BE_.D1.80.D0.B0.D1.81.D1.81.D0.BA.D0.B0.D0.B6.D1.83_.D0.BF.D1.80.D0.BE_Radeon_ProRender">Отдельно расскажу про Radeon ProRender</span></h4>
<p>Я пробовал его завести на винде с Radeon R9 270, но ни разу не получалось — при попытке включения плагина Blender всегда падал. Как это решить я не понял, вопросы такие в интернете есть, а ответов — нет.
</p><p>А что на линуксе? А на линуксе — берём сборку Blender 2.93 с официального сайта и Radeon ProRender 3.1.0 опять же «для Ubuntu 20», скачиваем его и устанавливаем через Blender Addons -> Install… пробуем включить и получаем какой-то питоновый стектрейс со странной, не особо о чём-то говорящей, ошибкой.
</p><p>Гуглением выясняется, что проблема в том, что в ProRender есть файлик <tt>_cffi_backend.cpython-37m-x86_64-linux-gnu.so</tt> — он для Python 3.7, а официальная сборка блендера идёт с Python 3.9.
</p>
Соответственно, вся задача — найти <tt>_cffi_backend.cpython-39-x86_64-linux-gnu.so</tt>. Найти его легче всего в пакетах (<tt>apt-get install python3-cffi</tt>), там как раз тоже python 3.9, и сделать <pre class="bash"><span style="color: #c20cb9; font-weight: bold;">ln</span> <span style="color: #660033;">-s</span> <span style="color: #000000; font-weight: bold;">/</span>usr<span style="color: #000000; font-weight: bold;">/</span>lib<span style="color: #000000; font-weight: bold;">/</span>python3<span style="color: #000000; font-weight: bold;">/</span>dist-packages<span style="color: #000000; font-weight: bold;">/</span>_cffi_backend.cpython-<span style="color: #000000;">39</span>-x86_64-linux-gnu.so ~<span style="color: #000000; font-weight: bold;">/</span>.config<span style="color: #000000; font-weight: bold;">/</span>blender<span style="color: #000000; font-weight: bold;">/</span><span style="color: #000000;">2.93</span><span style="color: #000000; font-weight: bold;">/</span>scripts<span style="color: #000000; font-weight: bold;">/</span>addons<span style="color: #000000; font-weight: bold;">/</span>rprblender<span style="color: #000000; font-weight: bold;">/</span>_cffi_backend.cpython-<span style="color: #000000;">39</span>-x86_64-linux-gnu.so</pre> Этого хватает, чтобы ProRender таки завёлся.
<p>А что же умеет этот ProRender? Ну, ситуация следующая: первую тестовую сценку он рендерит с вполне неплохим качеством всего лишь за 20 секунд (Cycles тратит на неё примерно 1:20). Но если взять Barcelona Pavillion, то на нём, во-первых, результат рендера слегка отличается от Cycles (ну ладно, понятно, что движки разные), а во-вторых, и производительность не выдающаяся:
</p>
<ul><li> GPU only — 05:02</li>
<li> CPU+GPU — 07:00</li></ul>
<p>То есть CPU+GPU медленнее, чем просто GPU O_o. Не знаю, почему.
</p><p>Ещё могу отметить, что Environment-Based Lighting в ProRender делается чуть по-другому, чем в Cycles — в Cycles он делается через Nodes, а в ProRender только через отдельную настройку в панельке. Но работает вполне адекватно.
</p>
https://yourcmc.ru/wiki/%D0%91%D0%BB%D0%BE%D0%B3:%D0%92%D0%B8%D1%82%D0%B0%D0%BB%D0%B8%D0%B9_%D0%A4%D0%B8%D0%BB%D0%B8%D0%BF%D0%BF%D0%BE%D0%B2/2020-08-22_%D0%9F%D0%BE%D0%BB%D0%BD%D0%BE%D1%8D%D0%BA%D1%80%D0%B0%D0%BD%D0%BD%D0%B0%D1%8F_%D1%86%D0%B2%D0%B5%D1%82%D0%BE%D0%BA%D0%BE%D1%80%D1%80%D0%B5%D0%BA%D1%86%D0%B8%D1%8F,_KWin_%D0%B8_%D0%B4%D1%80%D0%B0%D0%B9%D0%B2%D0%B5%D1%80_Intel_IrisВиталий Филиппов — 2020-08-22 Полноэкранная цветокоррекция, KWin и драйвер Intel IrisVitaliyFilippovhttps://yourcmc.ru/wiki/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:VitaliyFilippov2020-08-22T23:11:09Z2020-08-22T23:13:56Z<p>Недавно на ноуте словил багов с Intel-овскими дровами, которые под Linux раньше были самые беспроблемные. Все полечил, хочу запротоколировать.
</p><p>В общем, суть такая: я использую нетривиальный ноутбук Samsung, у дисплея которого очень упоротая цветопередача. В остальном ноутбук отличный, поэтому я попереживал, что цвета не очень и написал себе свой собственный цветокорректор для KDE — в виде эффекта для оконного менеджера KWin.
</p><p>KWin вообще уже очень давно работает гораздо лучше Compiz-а и подобных, при этом умеет все те же самые эффекты. Как вспомню, как я прикручивал Compiz к Gnome 2 — о боже, какой это был глюкодром… А сейчас в KWin просто включаешь эффекты и всё — всё работает. Никаких тебе артефактов, никаких тебе падений.
</p><p>Ну, собственно, KDE вообще на порядок лучше гнома. До выхода гномощели (Gnome 3 / Gnome Shell) они шли примерно ноздря в ноздрю и я переходил то на гном, то обратно на KDE, но гномощель отбросила гном назад лет на 20, поэтому теперь — только KDE.
</p><p>В общем вот. Я использую собственный эффект для KDE, который делает полноэкранную ICC-цветокоррекцию через шейдер: <a rel="nofollow" class="external free" href="https://github.com/vitalif/kwin">https://github.com/vitalif/kwin</a>
</p><p>И вдруг на тебе! Обновляю систему, пересобираю свой плагин для KWin 5.17 (до этого был 5.14) и вместо эффектов весь экран в каких-то диких артефактах.
</p><p>Чешу репу, лезу пробовать настраивать драйвер intel в Xorg. В общем все похождения описывать не буду — задолбаюсь — но прихожу к тому, что опция AccelMethod=UXA помогает, с ней эффект работает нормально. Успокаиваюсь.
</p><p>Через некоторое время начинает проявляется ещё один баг — ИНОГДА подвисает отрисовка (картинка на экране). При этом можно переключиться в консоль (Ctrl-Alt-F1) и обычно даже переключиться обратно, и всё отлипает. Нахожу какой-то баг с GPU Lockup-ами, который кто-то обходил через опцию ядра <tt style="border: 1px gray dashed; padding: 4px; background: #f8f8f8">i915.enable_psr=0</tt>, прописываю, подвисания уходят. Успокаиваюсь снова.
</p><p>В итоге обнаруживается ещё более прикольная вещь — тормозит GTK. Если открыть любое GTK-приложение, например, Gimp, процесс Xorg начинает жрать 100 % CPU, а отрисовка дико тормозить. Особенно заметно это, если в Gimp сделать квадратное выделение, нагрузку на иксы создаёт ползущий пунктирчик выделения.
</p><p>В общем, да — оказывается, GTK тормозит при AccelMethod=UXA. Выключаю AccelMethod=UXA, эффекты отваливаются обратно. Тогда решаю проверить под новым, тестовым, пользователем на том же ноутбуке — опа, обнаруживаю, что эффекты работают. Обнуляю свой конфиг KWin (kwinrc) и настраиваю эффект заново — опа, и под моим пользователем работает. Виновата была какая-то опция, оставшаяся от прошлых времён. Окончательно радуюсь — эффекты работают, GTK не тормозит.
</p><p>Но не даёт покоя вопрос: а из-за чего вообще-то произошёл такой геморрой?
</p><p>А оказалось всё просто. С обновлениями системы приехала Mesa 20, а в ней для интела включили по умолчанию новый драйвер iris_dri. Когда я это понял, конечно, сразу его отключил переменной окружения MESA_LOADER_DRIVER_OVERRIDE=i965. А отключил бы сразу — и всего вышеупомянутого бы не было :-).
</p><p>В общем, вот такая ситуация. Iris всё ещё сыроват.
</p>
https://yourcmc.ru/wiki/%D0%91%D0%BB%D0%BE%D0%B3:%D0%92%D0%B8%D1%82%D0%B0%D0%BB%D0%B8%D0%B9_%D0%A4%D0%B8%D0%BB%D0%B8%D0%BF%D0%BF%D0%BE%D0%B2/2020-08-14_mdadm_shrinkВиталий Филиппов — 2020-08-14 mdadm shrinkVitaliyFilippovhttps://yourcmc.ru/wiki/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:VitaliyFilippov2020-08-14T14:22:34Z2020-08-14T14:22:35Z<p>Пипец, чуть с ума щас не сошёл. Вроде такая простая задача, а протрахался… :)
</p><p>Дано: mdadm RAID1 (зеркало) из /dev/sda2 и /dev/sdb2, и это rootfs. Надо немного уменьшить разделы на диске. Ну, я думаю — что тут сложного:
</p>
<ol><li> Перезагружаемся в initramfs (в Debian опция ядра break=mount), прихватив с собой busybox, resize2fs и sfdisk (и нужные им библиотеки), ну или делаем извращение типа <a rel="nofollow" class="external text" href="https://unix.stackexchange.com/questions/226872/how-to-shrink-root-filesystem-without-booting-a-livecd/227318#227318">такого</a>, но перезагрузиться проще</li>
<li> Уменьшаем ФС — <tt style="border: 1px gray dashed; padding: 4px; background: #f8f8f8">resize2fs /dev/md0 <SIZE>K</tt></li>
<li> Уменьшаем RAID — <tt style="border: 1px gray dashed; padding: 4px; background: #f8f8f8">mdadm --grow --size=<SIZE> /dev/md0</tt></li>
<li> Останавливаем RAID — <tt style="border: 1px gray dashed; padding: 4px; background: #f8f8f8">mdadm --stop /dev/md0</tt></li>
<li> Меняем размеры разделов sfdisk-ом — <tt style="border: 1px gray dashed; padding: 4px; background: #f8f8f8">sfdisk --dump /dev/sda > sda.txt; vi sda.txt; sfdisk /dev/sda < sda.txt; sfdisk /dev/sdb < sdb.txt</tt> — конечно, правильно их рассчитав по <tt style="border: 1px gray dashed; padding: 4px; background: #f8f8f8">mdadm --examine /dev/sda</tt> сложением Data Offset + 2*Array Size (он в килобайтах).</li>
<li> Запускаем RAID обратно — <tt style="border: 1px gray dashed; padding: 4px; background: #f8f8f8">mdadm --assemble --scan</tt></li></ol>
<p>И вот на последнем этапе схема даёт сбой:
</p>
<pre>
/ # mdadm --assemble --scan
mdadm: failed to add /dev/sdb2 to /dev/md/0: Invalid argument
mdadm: failed to add /dev/sda2 to /dev/md/0: Invalid argument
mdadm: failed to RUN_ARRAY /dev/md/0: Invalid argument
</pre>
<p>Причём я априори в курсе, что старые версии суперблока mdadm хранятся в конце раздела и изменение раздела не переживают — но в данном случае версия суперблока изначально 1.2, так что этой проблемы быть не должно.
</p><p>Разгадка: эта тварь хранит размер каждого устройства в его суперблоке, и отказывается запускаться, когда реальный размер не соответствует сохранённому. Но есть способ его обновить — для этого на последнем этапе надо просто сказать <tt style="border: 1px gray dashed; padding: 4px; background: #f8f8f8">mdadm --assemble -U devicesize /dev/md0 /dev/sda2 /dev/sdb2</tt>.
</p>
https://yourcmc.ru/wiki/%D0%91%D0%BB%D0%BE%D0%B3:%D0%92%D0%B8%D1%82%D0%B0%D0%BB%D0%B8%D0%B9_%D0%A4%D0%B8%D0%BB%D0%B8%D0%BF%D0%BF%D0%BE%D0%B2/2020-01-14_%D0%9F%D1%80%D0%BE_%22%D1%8D%D1%84%D1%84%D0%B5%D0%BA%D1%82%D0%B8%D0%B2%D0%BD%D1%8B%D0%B5%22_%22%D0%BD%D0%B0%D0%B4%D1%91%D0%B6%D0%BD%D1%8B%D0%B5%22_%D0%BC%D0%B8%D0%BA%D1%80%D0%BE%D1%81%D0%B5%D1%80%D0%B2%D0%B8%D1%81%D1%8BВиталий Филиппов — 2020-01-14 Про "эффективные" "надёжные" микросервисыVitaliyFilippovhttps://yourcmc.ru/wiki/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:VitaliyFilippov2020-01-14T20:37:40Z2020-01-17T14:25:41Z<p>На хайлоад в этом году не ходил, но услышал от коллеги про доклад … про вот этот вот доклад (на хайлоаде был он же):
</p><p><a rel="nofollow" class="external free" href="https://2019.jokerconf.com/2019/talks/4wj9og0tij3wpxe3ourovr/">https://2019.jokerconf.com/2019/talks/4wj9og0tij3wpxe3ourovr/</a>
</p><p>Вкратце: выходит дядька и говорит, что вот, в типичной веб-архитектуре с БД, memcached и stateless приложением очень большие затраты на маршалинг и демаршалинг [дядя реальный олд, раз сериализация у него маршалинг — но на это забьём]. Конкретно, до 85 % времени на это дело якобы уходит.
</p><p>Поэтому они взяли Кассандру, засунули её прямо в Java процесс с приложением, и общаются с ней локально. Типа она распределённая, поэтому всё остаётся отказоустойчиво — она синхронизируется с другими нодами. И типа поэтому всё хорошо.
</p><p>И вот с чего я тут охреневаю — это с 85 % затрат на сериализацию. Ну треш же какой-то! Ладно, ява, ну и что — <a rel="nofollow" class="external free" href="https://github.com/fabienrenaud/java-json-benchmark">https://github.com/fabienrenaud/java-json-benchmark</a> - вот бенч разных библиотек JSON для явы. Самая быстрая даёт ~800 тысяч разборов и ~1.5 млн кодирований по 1 КБ в секунду, да и банальный Jackson не сильно отстаёт: ~500к / ~1 м.
</p><p>Оказывается, 85 % это ссылка на статью: <a rel="nofollow" class="external free" href="https://research.google/pubs/pub48030/">https://research.google/pubs/pub48030/</a>. Статья тоже кривая. Не объясняя, ЧТО они тестировали, они действительно приводят цифры в оверхед сериализации в 45 % CPU и 85 % передачи лишних данных по сети и на основании этого агитируют за написание stateful бэкенда.
</p><p>Если присмотреться внимательнее, там, правда, есть пометка:
</p>
<blockquote>
<p>Finally, our experiments in Section 3 show that if only part of the record is needed (10 %), RInK stores incur both extra CPU (46 %) and network (85 %) costs
</p>
</blockquote>
<blockquote>
<p>For example, consider anapplication that caches the address books for all online usersin aRInKstore: for each user, the address book is stored as asingle key-value pair. If a request arrives from Alice to readBob’s phone number from her address book, all of Alice’scontacts must be fetched and unmarshalled, even thoughonly a small portion of the data is needed.
</p>
</blockquote>
<p>Б**дь! Ну так не надо так писать, чтобы для чтения 1 номера телефона приложение читало всю адресную книгу!!!
</p><p>А к дядьке этому у меня один вопрос — он сам вообще что-то сравнивал? Или как всегда — «потому что можем»?
</p><p>Каждый раз немного удивляюсь от их микросервисо-джабба-страданий… они же ими балуются ещё с тех пор, когда их не называли микросервисами. И в страданиях изобретали сначала собственный java-сериализатор, потом собственный кэш, сначала борясь с gc, а потом забив и уйдя куда-то на разделяемую память. Вылысыпыдысты.
</p><p>Ну ладно. «Ночью через лес», когда файловое хранилище на postgresql изобретал, тоже сначала бодрый был.
</p>
https://yourcmc.ru/wiki/%D0%91%D0%BB%D0%BE%D0%B3:%D0%92%D0%B8%D1%82%D0%B0%D0%BB%D0%B8%D0%B9_%D0%A4%D0%B8%D0%BB%D0%B8%D0%BF%D0%BF%D0%BE%D0%B2/2019-02-06_%D0%9D%D0%BE%D1%87%D1%8C%D1%8E_%D1%87%D0%B5%D1%80%D0%B5%D0%B7_%D0%BB%D0%B5%D1%81Виталий Филиппов — 2019-02-06 Ночью через лесVitaliyFilippovhttps://yourcmc.ru/wiki/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:VitaliyFilippov2019-02-06T14:40:47Z2020-11-16T16:01:25Z<p>Про доклад «Ночью через лес»… <a rel="nofollow" class="external free" href="https://youtu.be/oMQLR-BhnJU">https://youtu.be/oMQLR-BhnJU</a>
</p><p>…по болоту на тандемном велосипеде с крыльями.
</p><p>Ко мне тут (4.02.2019) однокурсник обратился с вопросом — типа он там щас работает в этой конторе. У них хранилище ФАЙЛОВ (30-50 тб, правда, в основном мелких) в Кассандре. Было то ли на 4 то ли на 8 серверах, диски в RAID-ах и поверх bcache.
</p><p>Щас они этот кластер — внимание! — переместили в один сервер в докеры, оставив 16 дисков и 16 узлов (но убрав bcache), то есть теперь 16 кассандр в одном сервере (зачем? потому что так дешевле).
</p><p>И вот короче встал вопрос: извне всего ~137 rps, объекты по <= 64 кб. 64кб*137 = всего где-то ~9 мбайт/с. Но при этом 16 дисков (HDD) загружены по самое не балуйся, на каждом чтение >= 100 мбайт/с. Вопрос: какогохуя?)))
</p><p>Я его спросил — а на#уя в кассандре? — а он мне скинул ссылку на этот доклад — я открыл, начал смотреть и думаю — б#я! я же помню этого мужика!
</p><p>И точно — он в 2012 году на highload рассказывал, как пи#дато файлы в postgres-е хранить: <a href="https://yourcmc.ru/wiki/Highload-2012:_%D0%9E%D1%82%D1%87%D1%91%D1%82_%D0%92%D0%B8%D1%82%D0%B0%D0%BB%D0%B8%D1%8F_%D0%A4%D0%B8%D0%BB%D0%B8%D0%BF%D0%BF%D0%BE%D0%B2%D0%B0#.D0.A1.D0.BF.D0.B0.D1.81.D0.B5.D0.BD.D0.B8.D0.B5_6_.D0.BC.D0.BB.D0.BD_.D1.84.D0.B0.D0.B9.D0.BB.D0.BE.D0.B2_.D0.B2_.D1.83.D1.81.D0.BB.D0.BE.D0.B2.D0.B8.D1.8F.D1.85_.D0.BF.D0.BE.D0.BB.D0.BD.D0.BE.D0.B3.D0.BE_.D0.A5.D0.B5.D1.86.D0.BD.D0.B5.D1.80.D0.B0_.2F_.D0.94.D0.B0.D0.BD.D0.B8.D0.B8.D0.BB_.D0.9F.D0.BE.D0.B4.D0.BE.D0.BB.D1.8C.D1.81.D0.BA.D0.B8.D0.B9.2C_.D0.94.D0.BC.D0.B8.D1.82.D1.80.D0.B8.D0.B9_.D0.A1.D0.B8.D0.BC.D0.BE.D0.BD.D0.BE.D0.B2_.28Setup.ru.29" title="Highload-2012: Отчёт Виталия Филиппова">Highload-2012: Отчёт Виталия Филиппова#Спасение 6 млн файлов в условиях полного Хецнера / Даниил Подольский, Дмитрий Симонов (Setup.ru)</a>
</p><p>То есть типа сначала у них всё типа было просто в локальных ФС на двух серверах и синхронизировалось rsync-ом. Потом у них кончилось место на серверах, обход дерева директорий стал занимать очень много времени (8 часов), и они засунули файлы в postgresql с мастер-мастер репликацией.
</p><p>Потом оказалось, что крупные файлы неудобно хранить просто в поле и они их засунули в блобы. А потом обнаружили, что блобы не попадают в репликацию! Ну и в целом, что всё это грузит постгрю. Тогда они вынули из postgresql всё, что было больше 64к и сунули в LeoFS. LeoFS — это такая попытка сделать Ceph, но очень хреновая.
</p><p>Потом в leofs кончилось место, они попробовали добавить пару серверов… и leofs развалился на хрен. Они позвонили японцам-авторам, те их час послушали и сказали «простите, у нас кончилось время, до свидания».
</p><p>Они с помощью видимо такой-то матери убрали добавленные сервера обратно — и оно опять работало, пока в leofs не кончилось место окончательно.
</p><p>И тут… им пришла свежая мысль — засунуть это всё в aerospike. Засунули, на 8 серверов. И оно вроде опять заработало, да ещё и кластеризация автоматическая появилась. Про это был доклад уже в 2015 году.
</p><p>Продолжение я знаю уже из вопроса однокурсника: Aerospike их, видимо, тоже не устроил и сейчас у них всё это уже в кассандре!
</p><p>И вот этот дядя на Highload нам рассказывает, что Ceph, который под это идеален, они пробовали и им было медленно (да ещё и «ребаланс по каждому чиху, при котором кластер вообще нельзя эксплуатировать»)… Жопой чую — у них там и сеть была 1G, конечно, какой уж тут ребаланс…
</p><p>И это всё на продакшне. Эпично. Там ещё гениальный вопрос в конце доклада есть — типа, а вот когда у вас кончилось место в 2 серверах — почему вы… просто не добавили ещё 2?))))))) — «а чо, так можно было?…»
</p><p>Просто плотно проработав последние несколько лет с Ceph-ом слушать это мегаржачно! Это вот Ceph значит медленный, а кассандра, которая грузит все диски на 100 % — быстрая? И это у них ещё записи нет. Была бы запись, было бы примерно как с KVStore-ом, когда 80 % i/o занимал compaction (KVStore — это промежуточная попытка апгрейда хранилки в ceph между filestore и bluestore).
</p><p>Бэкапы он тоже не делает — ну, типа, реплика же есть, да и откуда ещё 30 тб взять.
</p><p>Третья серия — это второй доклад 2015 года — <a rel="nofollow" class="external free" href="https://youtu.be/bOqSexPzSIE?t=1702">https://youtu.be/bOqSexPzSIE?t=1702</a> - в нём он уже не такой весёлый и просто рассказывает, как всё сложно с этими вашими файловыми хранилищами.
</p>
https://yourcmc.ru/wiki/%D0%91%D0%BB%D0%BE%D0%B3:%D0%92%D0%B8%D1%82%D0%B0%D0%BB%D0%B8%D0%B9_%D0%A4%D0%B8%D0%BB%D0%B8%D0%BF%D0%BF%D0%BE%D0%B2/2018-06-27_%D0%A2%D0%B5%D1%81%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D1%80%D0%B0%D0%B7%D0%BB%D0%B8%D1%87%D0%BD%D1%8B%D1%85_%D1%81%D0%BF%D0%BE%D1%81%D0%BE%D0%B1%D0%BE%D0%B2_%D0%BF%D0%BE%D0%B4%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D1%8F_SSD_%D0%B4%D0%BB%D1%8F_CephВиталий Филиппов — 2018-06-27 Тестирование различных способов подключения SSD для CephVitaliyFilippovhttps://yourcmc.ru/wiki/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:VitaliyFilippov2018-06-27T15:19:47Z2020-08-14T19:57:01Z<p>Задача: проверить гипотезу, что дешёвые SSD без конденсаторов можно подключать к системе через RAID контроллер с батарейкой для получения приличных IOPS-ов в Ceph (хотя это и извращение).
</p><p>TL;DR: похоже, можно. IOPS-ы растут, а данные потерять не удалось. Но, конечно, это всё равно в некоторой мере стрельба в ногу, поэтому лучше просто купить недорогие Enterprise SSD с «advanced power loss protection» типа Micron 5100/5200.
</p><p><b>UPD: Предложенную идею официально считать дичью, делать так не надо.</b>
</p><p>Задача: проверить гипотезу, что дешёвые SSD без конденсаторов можно подключать к системе через RAID контроллер с батарейкой для получения приличных IOPS-ов в Ceph (хотя это и извращение).
</p><p>TL;DR: похоже, можно. IOPS-ы растут, а данные потерять не удалось. Но, конечно, это всё равно в некоторой мере стрельба в ногу, поэтому лучше просто купить недорогие Enterprise SSD с «advanced power loss protection» типа Micron 5100/5200.
</p><p><b>UPD: Предложенную идею официально считать дичью, делать так не надо.</b>
</p>
<h2><span class="mw-headline" id=".D0.9F.D1.80.D0.B5.D0.B0.D0.BC.D0.B1.D1.83.D0.BB.D0.B0">Преамбула</span></h2>
<p>Особенность Ceph — то, что вся запись (даже та, для которой никто этого явно не просит) ведётся транзакционно.
</p><p>В силу этого IOPS-ы при записи мелкими блоками, то бишь при OLTP-применении, страдают. В силу этого же тестировать производительность дисков нужно обязательно с опцией fdatasync=1.
</p><p>И в силу этого же нужно использовать SSD с <b>конденсаторами</b> (точнее — суперконденсаторами, ионисторами). Конденсаторы — это самое важное отличие Enterprise SSD от дешёвых Desktop SSD и служат они для защиты внутреннего кэша записи при отключении питания. Когда отключается питание, заряда конденсаторов хватает, чтобы SSD успела сбросить недозаписанное содержимое кэша во флеш-память. Это даёт ей возможность игнорировать запросы синхронизации данных (fsync, SATA FLUSH CACHE) и таким образом на порядок-два повышать производительность <b>транзакционной</b> записи (разницу по IOPS можно видеть ниже).
</p><p>Конденсаторы называются «Расширенная защита от потери данных при отключении питания» / «Enhanced Power Loss Protection». В данном тесте этой характеристикой обладают Intel DC3500 и Intel 320.
</p><p>…Но…
</p><p>Есть же в природе серверные RAID контроллеры, тоже с батарейками/конденсаторами, служащими ровно той же цели. Может быть, можно подключить SSD через такой контроллер и получить повышенную производительность?
</p><p>Сразу скажем: IOPS-ы при разных способах подключения различаются драматически и местами довольно странно.
</p><p>Все тесты запускались утилитой fio с параметрами: <tt style="border: 1px gray dashed; padding: 4px; background: #f8f8f8">fio -ioengine=libaio -fdatasync=1 -direct=1 -invalidate=1 -name=test -bs=4k -size=10G -iodepth=16 -rw=randwrite -filename=/dev/sdX</tt> (то есть, случайная запись блоками по 4 килобайта в обход кэша ОС (direct и invalidate) и в транзакционном режиме (fdatasync)).
</p><p>Протестированные виды подключения:
</p>
<ul><li> Через контроллер Adaptec 6805 с ZMM (конденсатором):
<ul><li> RAID volume из одного диска. В этом случае доступны две настройки: внутренний кэш диска — вкл/выкл и кэш контроллера — вкл/выкл.</li>
<li> JBOD из одного диска. В этом случае доступна одна настройка: внутренний кэш диска — вкл/выкл.</li></ul></li>
<li> Через SATA контроллер обычной десктопной материнской платы. Доступна одна настройка: внутренний кэш диска — вкл/выкл (через утилиту hdparm -W).</li></ul>
<h2><span class="mw-headline" id=".D0.A0.D0.B5.D0.B7.D1.83.D0.BB.D1.8C.D1.82.D0.B0.D1.82.D1.8B_.D1.82.D0.B5.D1.81.D1.82.D0.B8.D1.80.D0.BE.D0.B2.D0.B0.D0.BD.D0.B8.D1.8F">Результаты тестирования</span></h2>
<table class="wikitable">
<tr>
<th>Модель SSD / Подключение
</th>
<th>RAID,
<p>оба кэша ВЫКЛ
</p>
</th>
<th>RAID,
<p>кэш диска ВКЛ
</p>
</th>
<th>RAID,
<p>кэш RAID вкл
</p>
</th>
<th>RAID,
<p>оба кэша ВКЛ
</p>
</th>
<th>JBOD,
<p>кэш диска выкл
</p>
</th>
<th>JBOD,
<p>кэш диска вкл
</p>
</th>
<th>SATA,
<p>кэш диска выкл
</p>
</th>
<th>SATA,
<p>кэш диска вкл
</p>
</th>
<th>Без
<p>fdatasync
</p>
</th></tr>
<tr>
<td>Intel DC3500 SSDSC2BB080G4 80GB
</td>
<td bgcolor="#C0FFC0">25000
</td>
<td>7000
</td>
<td>9500
</td>
<td bgcolor="#D0D0FF">9500
</td>
<td bgcolor="#C0FFC0">26000
</td>
<td bgcolor="#FFC0C0">5000
</td>
<td bgcolor="#C0FFC0">21000
</td>
<td>7000
</td>
<td>26000
</td></tr>
<tr>
<td>Intel X25-M SSDSA2M160G2GC 160GB
</td>
<td bgcolor="#FFC0C0">1100
</td>
<td bgcolor="#C0FFC0">21000
</td>
<td bgcolor="#FFC0C0">1100
</td>
<td bgcolor="#D0D0FF">9000
</td>
<td bgcolor="#FFC0C0">1100
</td>
<td>5000
</td>
<td bgcolor="#FFC0C0">1100
</td>
<td>5000
</td>
<td>21000
</td></tr>
<tr>
<td>Intel 320 SSDSA2CW160G3 160GB
</td>
<td bgcolor="#C0FFC0">20000
<p>↓ 14000<sup id="cite_ref-1" class="reference"><a href="#cite_note-1">[1]</a></sup>
</p>
</td>
<td bgcolor="#C0FFC0">20000
<p>↓ 14000
</p>
</td>
<td>9500
</td>
<td bgcolor="#D0D0FF">9500
</td>
<td bgcolor="#C0FFC0">20000<sup id="cite_ref-2" class="reference"><a href="#cite_note-2">[2]</a></sup>
</td>
<td>4500
</td>
<td>9500
</td>
<td>8000
</td>
<td>20000
</td></tr>
<tr>
<td>Intel 545s SSDSC2KW256G8 256GB
</td>
<td bgcolor="#FFC0C0">1100
</td>
<td bgcolor="#C0FFC0">33000
</td>
<td bgcolor="#FFC0C0">1150
</td>
<td bgcolor="#D0D0FF">9000
</td>
<td bgcolor="#FFC0C0">1100
</td>
<td>то 2100,
<p>то 700
</p>
</td>
<td bgcolor="#FFC0C0">1100
</td>
<td>то 2600,
<p>то 800<sup id="cite_ref-3" class="reference"><a href="#cite_note-3">[3]</a></sup>
</p>
</td>
<td>33000
</td></tr></table>
<p>Последняя колонка — для справки, чтобы видеть верхнюю границу возможной скорости.
</p><p>21000-26000 можно воспринимать как одинаковые цифры, так как скорость записи на один и тот же SSD на самом деле может варьироваться от теста к тесту и чтобы её установить точно, нужно более расширенное и долгое тестирование с представлением результатов в виде графиков.
</p><p>Результаты приведены при нагрузке на один диск. Если дать параллельную нагрузку на 3 первых из списка диска, фактические iops-ы снижаются в 2 раза — в своём оптимальном режиме 12500, а во втором по оптимальности (с обоими включенными кэшами) — до 4500. Возможно, это обусловлено тем, что тестировался уже не самый новый и не самый быстрый RAID-контроллер (хотя SATA 6 GB/s вроде поддерживает).
</p>
<h2><span class="mw-headline" id=".D0.9F.D1.80.D0.B8.D0.BC.D0.B5.D1.87.D0.B0.D0.BD.D0.B8.D1.8F">Примечания</span></h2>
<ol class="references">
<li id="cite_note-1"><span class="mw-cite-backlink"><a href="#cite_ref-1">↑</a></span> <span class="reference-text">Снижается до 13000-15000 iops через 3-5 Гб записанных данных</span>
</li>
<li id="cite_note-2"><span class="mw-cite-backlink"><a href="#cite_ref-2">↑</a></span> <span class="reference-text">В JBOD тот же диск почему-то не снижает скорость — х.з почему.</span>
</li>
<li id="cite_note-3"><span class="mw-cite-backlink"><a href="#cite_ref-3">↑</a></span> <span class="reference-text">процесс тестирования идёт примерно так: 25 секунд 2600 iops, потом 8 секунд 800 iops, потом опять 25 секунд 2600 iops, опять 8 секунд 800… То есть получается, что 256 Мб пишется на полной скорости, а потом 25 Мб в 3 раза медленнее. С одной стороны, это какой-то намёк на сброс кэша, но с другой — бред полный, так как в режиме НЕтранзакционной записи (без fdatasync=1) с включённым кэшем теми же 4к-блоками тот же SSD выдаёт стабильно 22000-25000 IOPS. А с выключенным 1100 iops.</span>
</li>
</ol>
<h2><span class="mw-headline" id=".D0.A3.D0.BC.D0.BE.D0.B7.D0.B0.D0.BA.D0.BB.D1.8E.D1.87.D0.B5.D0.BD.D0.B8.D1.8F">Умозаключения</span></h2>
<p>В целом, если немножко вдуматься, результаты не очень очевидные. Объяснение им в моём понимании такое:
</p>
<ul><li> На серверных SSD внутренний кэш записи может тормозить транзакционную запись. Отсюда 7000 на DC3500.</li>
<li> На дешёвых SSD внутренний кэш записи помогает транзакционной записи, но не сильно. Отсюда 2600/800 на 545s и 5000 на X25. Либо, возможно, кроме волатильного кэша у них есть ещё и неволатильный (например, маленькая область SLC флеш памяти) и при отключении кэша отключаются оба, а при включении и fsync «отключается» только волатильный.</li>
<li> На дешёвых SSD при выключенном внутреннем кэше записи скорость <b>не</b>транзакционной записи очень сильно проседает (до скорости транзакционной), в итоге, даже если включить RAID-кэш — остаются тормоза, так как кэш не успевает сбрасываться на диск. Отсюда 1100 на X25 и 545s в режиме, когда включён только RAID-кэш.</li>
<li> Самая большая загадка — почему дешёвые SSD быстрые в режиме Write-Through (выключенного) RAID кэша при включенном внутреннем? Ответ может быть только один — в Write-Through («как бы отключённом») режиме кэша RAID контроллер тоже игнорирует запросы fsync. Остаётся только надеяться, что «Write-Through» фактически означает «записать в кэш, подтвердить запись и сразу передать на диск» — в этом случае при отключении питания данные всё-таки останутся в кэше и при следующем включении доедут до назначения. А вот если WT означает «пишем мимо кэша», то это просто отключение транзакционности и при отключении питания данные, скорее всего, повредятся. Чтобы проверить, как оно в реальности, проведены дополнительные тесты:
<ul><li> Простой тест записи пройден. Тест такой: пишем с максимальной скоростью 2 Гб, делаем fsync, выдёргиваем питание, включаем и проверяем, что все 2 гб записались.</li>
<li> Более сложный тест записи тоже пройден. Тест такой: запускаем на машине программу, который пишет по 1 случайному блоку в случайное место на диске, после каждой записи делает fsync и рапортует по сети второй машине, что только что записала. В процессе записи выдёргиваем питание, потом включаем обратно, копируем лог на тестируемую машину и проверяем, что все данные записались. По сути, программа изображает из себя СУБД, а проверка — то, что все закоммиченные транзакции записаны на диск. Скрипты, которыми тестировал: <a rel="nofollow" class="external free" href="http://yourcmc.ru/git/vitalif/fsync-check">http://yourcmc.ru/git/vitalif/fsync-check</a></li>
<li> Вывод: по-видимому, Write-Through кэш тоже защищён батарейкой, а значит, RAID контроллеры можно использовать.</li></ul></li></ul>
<h2><span class="mw-headline" id=".D0.92.D1.8B.D0.B2.D0.BE.D0.B4.D1.8B">Выводы</span></h2>
<ul><li> Оптимальный способ подключения серверных SSD — SATA с выключенным кэшем (hdparm -W 0 /dev/sdX), либо SAS RAID контроллер с обоими отключенными кэшами (arcconf setcache 1 device 0 5 wt && arcconf setcache 1 logicaldrive 5 wt). SATA лучше, так как в этом случае поддерживается TRIM (хотя в нём серверные SSD и не нуждаются), а RAID-контроллер точно не может быть узким местом.</li>
<li> Оптимальный способ подключения дешёвых настольных SSD — SAS RAID контроллер с включённым кэшем диска и выключенным (write-through) кэшем RAID-контроллера.</li>
<li> При подключении через RAID контроллер и включении обоих кэшей записи получается некоторая гарантированно неплохая скорость. «Гарантированная» в том смысле, что не сильно зависит от модели SSD, так как упирается в скорость работы самого контроллера.</li>
<li> Способа обеспечить нормальные IOPS-ы на запись с Ceph два:
<ul><li> <b>Предпочтительный:</b> Серверные SSD + SATA/NVMe подключение</li>
<li> RAID контроллер с конденсатором. Но желательна поддержка скорости SATA 12 GB/s и хотя бы 1 Гб кэша (в противном случае контроллер сам может стать узким местом)</li></ul></li></ul>
https://yourcmc.ru/wiki/%D0%91%D0%BB%D0%BE%D0%B3:%D0%92%D0%B8%D1%82%D0%B0%D0%BB%D0%B8%D0%B9_%D0%A4%D0%B8%D0%BB%D0%B8%D0%BF%D0%BF%D0%BE%D0%B2/2018-06-26_%D0%9F%D0%B5%D0%BD%D1%81%D0%B8%D0%BE%D0%BD%D0%BD%D0%B0%D1%8F_%D0%BC%D0%B0%D1%82%D0%B5%D0%BC%D0%B0%D1%82%D0%B8%D0%BA%D0%B0Виталий Филиппов — 2018-06-26 Пенсионная математикаVitaliyFilippovhttps://yourcmc.ru/wiki/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:VitaliyFilippov2018-06-25T21:46:17Z2018-06-25T21:46:18Z<p>В тему повышения пенсионного возраста, которое щас хотят внедрять наши горячо любимые вожди.
</p><p>Можно заюзать вот такую математику.
</p><p>Если предположить, что:
</p>
<ul><li> пенсии субсидируются исключительно налогом с зарплат</li>
<li> средняя зарплата в стране 36000 руб</li>
<li> средняя пенсия в стране 14000 руб</li>
<li> количество пенсионеров 30 %</li>
<li> количество работающих 54 %</li></ul>
<p>(все цифры взяты из интернетов, предположим что близки к реальности)
</p><p>Тогда налог будет 14/36*30/54 = 21,6 %
</p><p>Что характерно, весьма близко к реальности — реальность 22 %.
</p><p>С одной стороны, правда, в среднем в реальности меньше, так как всякие льготы и «регрессивная» шкала налога. С другой стороны, вроде и ПФР субсидируется не только налогом с зп. Ну и сам очевидно жрёт — но поисследовать сколько он жрёт вопрос к исследователям типа ФБК ну и не знаю,… ФСБ там.
</p><p>В общем, если так смотреть — то вроде:
</p>
<ul><li> по мне как-то не видно явной необходимости повышать возраст.</li>
<li> реальная проблема России в низких зарплатах. из-за низких зарплат и пенсии низкие.</li></ul>
<p>А, да, и ещё соответственно накопительная система была в принципе тоже логичным решением проблемы — тогда типа убралось бы «усреднение» — у кого зп большая, была бы и пенсия большая (в теории), а у кого маленькая — была бы и пенсия маленькая. Но «получилось как всегда», так как у будущих бабушек в усть-задрищенске зарплата мизерная, а содержать их надо (ну в принципе логично что надо — вроде там это… помощь незащищённым слоям населения и всё такое). Вот и закопали её видимо.
</p><p>Но по сути правильное решение — постараться обеспечить рост средней з/п по стране + оптимизировать нецелевые расходы ПФР (в России же живём, наверняка там их можно найти) + продолжать сколько-то субсидировать, наверное.
</p><p>И ещё на самом деле сам этот налог — для мелкого бизнеса идиотский совершенно. Вот допустим ты ИП и работаешь на себя — платишь только фиксированный взнос 28000 в год в ПФР и 6 % налога с выручки.
</p><p>А потом вдруг хочешь нанять ОДНОГО сотрудника и хренак!!! Сразу 43 % налога!!! Из которых 22 % это ПФР, 8 % прочее и 13 % НДФЛ. И ещё твои 6 % тоже ведь никуда не деваются.
</p><p>Как-то это тупо, разрыв слишком огромный. Выходит либо никого не оформляй и работай в чёрную, либо оформляй на 10000 руб оклад и снижай ту самую среднюю з/п по стране, либо ищи где-то лишних 43 % бабла, что для мелкого бизнеса весьма проблематично.
</p><p>Какой-то более мягкий переход должен быть, тогда мелочь повылезает из чёрных/серых окладов и небось и средняя з/п тоже повысится и фактические отчисления в ПФР…
</p>
https://yourcmc.ru/wiki/%D0%91%D0%BB%D0%BE%D0%B3:%D0%92%D0%B8%D1%82%D0%B0%D0%BB%D0%B8%D0%B9_%D0%A4%D0%B8%D0%BB%D0%B8%D0%BF%D0%BF%D0%BE%D0%B2/2018-01-01_%D0%92%D1%81%D1%91-%D1%82%D0%B0%D0%BA%D0%B8_Redux_-_%D0%BE%D1%82%D1%81%D1%82%D0%BE%D0%B9Виталий Филиппов — 2018-01-01 Всё-таки Redux - отстойVitaliyFilippovhttps://yourcmc.ru/wiki/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:VitaliyFilippov2018-01-01T19:22:06Z2018-01-01T19:22:07Z<p>Всё-таки Redux кривоват.
</p><p>Ну просто вот пример — есть там, не знаю, в приложении таблица «города», и надо сделать компонент подсказки городов — автокомплит.
</p><p>Есть библиотечный автокомплит, поверх к нему, соответственно, надо дописать функцию, которая подгружает сами данные, чтобы дальше использовать в ДВУХ и более местах приложения БЕЗ копипастинга. Например просто два поля подряд даже вставить — ну типа город1, город2, или город юзера / город компании, или ещё что-нибудь.
</p><p>Состояние у автокомплита — это:
</p>
<ol><li> введённый текст (не обязательно совпадающий с выбранным значением)</li>
<li> текущие подгруженные опции</li>
<li> выбранное значение (но оно, по идее — не его личное состояние, а кусок тех данных, которые собственно редактируются в этом поле)</li></ol>
<p>И действия:
</p>
<ol><li> обработать изменение введённого текста (подождать 200мс, отправить запрос на подгрузку опций)</li>
<li> обработать ответ на запрос подгрузки — залить опции в состояние</li>
<li> обработать событие выбора опции — залить выбранное значение в состояние</li></ol>
<p>Вопрос: КУДА всё это пихать?
</p><p>Если Redux, то Redux говорит, что вроде как ВСЁ пихать в Store. Но Store глобальный => получается, что когда ты вставляешь в ДВА или более места свой компонент, ты должен:
</p>
<ol><li> заставить его брать данные из РАЗНЫХ мест из стора</li>
<li> заставить его отправлять Reducer’у какие-то ДРУГИЕ действия (по-другому именованные видимо — типа «field1_load_autocomplete», «field2_load_autocomplete»)</li>
<li> потом ещё и заставить Reducer(ы) их обрабатывать</li></ol>
<p>Получается, что по идее ради 1 и 2 ты, как минимум, занимаешься копипастингом mapStateToProps/mapDispatchToProps/connect(), а ради 3 ты ещё и копипастишь обработчик action’а, или подключение обработчика, возможно через combineReducers(), но всё равно тебе как минимум один action в нём придётся как-то переопределить — чтобы значение-то итоговое сохранять туда, куда нужно.
</p><p>Вопрос: НА#УЯ всё это надо?
</p><p>Если с голым React’ом ты просто все эти обработчики ляпнешь прямо в компоненте, и стейт будет там же, а значение наружу будет передаваться колбэком.
</p><p>И в этом случае чтобы повторно использовать компонент ты как бы да, просто напишешь <tt><CityAutocomplete value=... onChange=... /></tt>.
</p><p>Не, я понимаю, что ВРОДЕ типа кажется круто полностью отделить работу с данными от рендера, ВРОДЕ типа круто при серверсайд рендеринге (подгрузил состояние и продолжил с того же момента), при извращениях типа живой отладки с сохранением состояния при изменении кода…
</p><p>Но если при этом теряется переиспользуемость компонентов — это какое-то фуфло.
</p><p>Короче, резюме: React, похоже, надо юзать голый, БЕЗ Redux’а.
</p>
https://yourcmc.ru/wiki/%D0%91%D0%BB%D0%BE%D0%B3:%D0%92%D0%B8%D1%82%D0%B0%D0%BB%D0%B8%D0%B9_%D0%A4%D0%B8%D0%BB%D0%B8%D0%BF%D0%BF%D0%BE%D0%B2/2017-12-14_%D0%98%D1%81%D1%82%D0%BE%D1%80%D0%B8%D1%8F_%D0%BE%D0%B4%D0%BD%D0%BE%D0%B3%D0%BE_%D0%BF%D1%80%D0%BE%D1%81%D0%B2%D0%B5%D1%82%D0%BB%D0%B5%D0%BD%D0%B8%D1%8F,_%D0%BF%D1%80%D0%BE%D0%B8%D0%B7%D0%BE%D1%88%D0%B5%D0%B4%D1%88%D0%B5%D0%B3%D0%BE_%D0%BF%D0%B0%D1%80%D1%83_%D0%BB%D0%B5%D1%82_%D0%BD%D0%B0%D0%B7%D0%B0%D0%B4Виталий Филиппов — 2017-12-14 История одного просветления, произошедшего пару лет назадVitaliyFilippovhttps://yourcmc.ru/wiki/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:VitaliyFilippov2017-12-14T16:35:06Z2017-12-14T22:59:51Z<p>Надо запротоколировать — прикольная история.
</p><p>Когда я на это напоролся, у меня было, собственно, открытие — я полностью прочувствовал, что PHP по дефолту не умеет обрабатывать 2 параллельных запроса от одного юзера.)))
</p><p>Суть такая: в PHP сделано тупое, но надёжное решение для исключения параллельной записи данных одной сессии двумя процессами — сессия тупо блокируется на весь период от её открытия до закрытия. А открывается она обычно в начале запроса — а закрывается в конце.))
</p><p>Следовательно, если никто ничего специально не предпринимал — 2 параллельных запроса от одного и того же юзера пхп выполнять не умеет :) ну то есть, например, невозможно параллельно открыть нескольких вкладок с одного сайта — они последовательно открываться будут.
</p><p>Оно понятно, зачем сделано — если не блокировать, то что окажется в итоге в сессии — неизвестно — два процесса могут писать в сессию параллельно и один может перезаписать данные другого. И оно обычно как бы не страшно, так как да, действительно сайтики редко кто так насилует, а если и насилует, то типа нефиг же — типа, тоже мне кулхацкер, у нас тут и так 100500 юзеров параллельно, а ты ещё и свои запросы хочешь в параллель пускать, падла?!
</p><p>И видимо, когда народ в PHP переключает сессию на redis и говорит, что всё стало «летать» — летать оно начинает именно потому, что redis хранилище сессий в пхп не делает блокировку — не то что это его фича — просто не умеет оно в блокировки :)
</p><p>А вот теперь история, как я на это напоролся:
</p><p>Ставил я VisualEditor (визуальный редактор для MediaWiki) и хотел его подружить с нашими правами (IntraACL). Для справки — в VisualEditor википеды же тоже прилично извратились — конфигурация там такая — сама вики на PHP, но рядом, чисто для VisualEditor’а, на сервер ставится node.js.
</p><p>В котором выполняется parsoid, служащий бэкендом к VisualEditor’у. Parsoid — это частично переписанный на js парсер медиавики — полностью не осилили и не осилят никогда, уж больно там говнокода много на него завязано.
</p><p>И запросы идут через такую жопу: браузер -> PHP -> node.js -> (а дальше нода же хочет получить текст страницы, которую правишь) -> обратно запрос в PHP.
</p><p>И по дефолту на втором запросе к PHP они его сессионную Cookie ему обратно не передавали. Соответственно, у нас из-за прав доступа отредактировать страницу не удавалось — но зато эта конструкция вообще работала! :)
</p><p>А когда я включил передачу куки юзера на этом запросе, чтобы нода читала текст страницы с учётом прав — вся эта конструкция стала радостно повисать. Я чуть башку не сломал, а оказывается, это была как раз блокировка сессии. Второй запрос же «вложен» в первый и запускается в той же сессии => 2 ждёт, пока кончится 1, а 1 ждёт, когда закончится 2. Дедлок.
</p><p>Вот тогда у меня и случилось просветление.))
</p><p>А после внедрения в медиавики неблокирующей работы с сессией, естественно, попёрли гонки и стала иногда отваливаться авторизация. Причём, почему-то, в том числе при вызове из скрипта репликации, который вообще однопоточный — там до сих пор гонка бывает, я так и не понял пока, откуда она там — для обычных-то юзеров поправили, конечно.
</p><p>И есть ещё вторая часть этой истории. Причём на неё я наткнулся даже раньше первой части, но в первый раз не понял, в чём была проблема. А повторно наткнулся, уже когда разобрался с сессиями.
</p><p>Короче: какая-то, с*ка, светлая голова в SemanticMediaWiki впилила для пересчёта какой-то очередной внутренней хрени обработчик очереди. Стандартной медиавиковской очереди — есть у неё в ядре очередь задач, и можно туда свои задачи пихать.
</p><p>Но так как стандартная обработка заданий идёт в том числе потихоньку в конце каждого запроса, после отдачи страницы юзеру (ну, типа, чтобы работало даже там, где демона не запустишь) — эта, с*ка, светлая голова решила, что это же будет тормозить! И реализовала обработку самого задания через дополнительный запрос с сервера на самого себя, к URLу который фактически обрабатывает задание.
</p><p>И оно как-то большей частью даже прокатывало… пока пользователь не открывал 2 вкладки одновременно — после чего висло нафиг 2 процесса сервера, а после N повторов висли все доступные процессы сервера и вики переставала отзываться. Причём все такие спокойные — загрузки CPU нет, никто ничем не занят, а вики висит — все в дедлоках.
</p><p>Сами википеды на свои сессии тоже вроде потом напоролись, но уже после меня (после 1.26) — и то ли в 1.27, то ли в 1.28, вроде, переосмыслили своё поведение.
</p>
https://yourcmc.ru/wiki/%D0%91%D0%BB%D0%BE%D0%B3:%D0%92%D0%B8%D1%82%D0%B0%D0%BB%D0%B8%D0%B9_%D0%A4%D0%B8%D0%BB%D0%B8%D0%BF%D0%BF%D0%BE%D0%B2/2016-09-23_Thin_RAID5Виталий Филиппов — 2016-09-23 Thin RAID5VitaliyFilippovhttps://yourcmc.ru/wiki/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:VitaliyFilippov2016-09-22T21:13:38Z2016-09-22T21:14:40Z<p>Блин. А есть в Linux’е что-нибудь такое, чтобы сделать RAID5, но без необходимости полного resync’а? То есть что-то типа thin provision, чтобы блоки под RAID выделялись по запросу. В идеале — чтобы оно при этом поддерживало извращённые схемы расположения, то есть например 3-дисковый (2 данные, 1 чётность) рейд на 4-х дисках 3+3+2+2 тб.
</p><p>Это кстати очень даже возможно — 3+3+2+2 нарезать на 6.66 тб RAID5! Схема такая: сначала кладём по 2тб на первые 3 диска, остаётся свободных 2*1тб и 1*2тб, кладём на них ещё по 1тб, остаётся 1тб свободный. Дальше забираем 0.33тб из первой группы с 1-го диска и 0.33тб из второй группы со второго диска и перекладываем на свободный 1тб, и на освободившееся место дописываем новую группу 3*0.33тб.
</p><p>То есть вот так схема выглядит:
</p>
<dl><dd>111422333</dd>
<dd>114222333</dd>
<dd>111222</dd>
<dd>333214</dd></dl>
<p>Вот. ceph так умеет, но он сетевой и распределённый, локально не поюзаешь. ZFS… «thin raid» умеет, но не умеет его расширять — то есть ещё диск не добавишь.
</p><p>А с LVM, например, нельзя так извратиться?
</p>
https://yourcmc.ru/wiki/%D0%91%D0%BB%D0%BE%D0%B3:%D0%92%D0%B8%D1%82%D0%B0%D0%BB%D0%B8%D0%B9_%D0%A4%D0%B8%D0%BB%D0%B8%D0%BF%D0%BF%D0%BE%D0%B2/2016-09-08_%D0%A2%D0%B5%D1%81%D1%82%D0%B8%D1%80%D0%BE%D0%B2%D0%B0%D0%BD%D0%B8%D0%B5_%D1%81%D0%BA%D0%BE%D1%80%D0%BE%D1%81%D1%82%D0%B8_%D0%B4%D0%B5%D1%88%D1%91%D0%B2%D0%BE%D0%B3%D0%BE_SSD_Silicon_Power_Slim_S55_120%D0%93%D0%B1Виталий Филиппов — 2016-09-08 Тестирование скорости дешёвого SSD Silicon Power Slim S55 120ГбVitaliyFilippovhttps://yourcmc.ru/wiki/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:VitaliyFilippov2016-09-08T09:31:39Z2016-09-08T09:34:22Z<p>Спойлер: Чтение приличное, а вот скорость записи — не очень (устоявшаяся 95 Мб/с).
</p><p>Отчёт о реальных скоростях данного SSD. Тестировал утилитой fio, под Linux. Глубина очереди везде 128, планировщик noop, слияние запросов в очереди для теста отключено. При снижении глубины очереди производительность сильно проседает; ну, так и не надо её снижать.
</p>
<ol><li> Последовательное чтение в идеальном случае (блоками >= 256кб) — 550 Мб/с</li>
<li> Последовательное чтение блоками по 4к — в среднем 190 Мб/с, но прилично колеблется в пределах 170—280 Мб/с</li>
<li> Последовательное чтение блоками по 8к — 370 Мб/с; по 16к — 450 Мб/с; по 32к — 500 Мб/с; по 64к — 530 Мб/с; по 128к — 540 Мб/с. Тут уже все цифры абсолютно стабильны, не колеблются.</li>
<li> Случайное чтение блоками по 4к — 170 Мб/с (~41000 iops), тоже колеблется в пределах 120—220 Мб/с.</li>
<li> Случайное чтение блоками по 8к — 305 Мб/с. По 16к — 340 Мб/с. По 32к — 380 Мб/с. По 64к — 440 Мб/с. По 128к — 510 Мб/с. По 256к — 535 Мб/с (это уже фактически последовательное чтение, а не случайное). Тут скорость опять стабильна, практически без колебаний.</li>
<li> Есть «псевдо-SLC кэш». Последовательная запись первых 2.4 Гб блоками по 4к — 244 Мб/с. Крупными блоками (>= 256к) — 490 Мб/с.</li>
<li> После 2.4 гб запись устаканивается на уровне 95 Мб/с, независимо от размера блока (SLC кэш кончается).</li>
<li> Скорость случайной записи абсолютно идентична скорости последовательной записи.</li>
<li> Скорость записи сохраняется постоянно, в том числе после полной перезаписи всего диска без TRIM.</li>
<li> 30 секунд простоя достаточно, чтобы SLC кэш сбросился и запись вернулась к 490 Мб/с.</li></ol>
<p>Наибольший «физический смысл» имеют случайные чтение/запись блоками 4к (стандартный размер блока ФС как в винде, так и в линуксе), а также последовательное чтение/запись блоками по 16к (так будет, если программа читает по 4к, а драйвер будет объединять соседние запросы), ну либо уже максимальными блоками (если программа копирует данные крупными блоками).
</p><p>В общем, с чтением всё ок, но огорчает устоявшаяся скорость записи, 95 Мб/с — для SSD мало. Хотя, наверное, за эти деньги ожидать чего-то сильно лучшего и не приходится.
</p>
https://yourcmc.ru/wiki/%D0%91%D0%BB%D0%BE%D0%B3:%D0%92%D0%B8%D1%82%D0%B0%D0%BB%D0%B8%D0%B9_%D0%A4%D0%B8%D0%BB%D0%B8%D0%BF%D0%BF%D0%BE%D0%B2/2016-09-07_%D0%A4%D0%A1_%D0%B4%D0%BB%D1%8F_%D1%84%D0%BB%D0%B5%D1%88%D0%B5%D0%BAВиталий Филиппов — 2016-09-07 ФС для флешекVitaliyFilippovhttps://yourcmc.ru/wiki/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:VitaliyFilippov2016-09-07T09:55:00Z2016-09-07T09:57:26Z<p>Давно уже люблю на всяких мелких/тестовых серверках / с флешек монтировать. Удобно — места под rootfs много не надо, а скорость чтения — что случайного, что последовательного — вполне адекватная.
</p><p>Другое дело, что случайная запись с обычными ФС типа ext4 очень медленная, флешки — это не SSD, гигагерцовых контроллеров и гигабайтов оперативки у них внутри нет — потому и Translation Layer внутри тупой, всё, что он обычно умеет — это «открыть» (стереть) и держать «открытыми» 2-3-4 блока стирания (обычно по 2 мб) и поддерживать в них последовательную запись. То есть, случайную запись мелкими блоками флешки не переваривают вовсе — iops на запись при этом обычно ограничивается 3-4 запросами в секунду.
</p><p>Стандартно это решается лог-структурированными ФС, которые никогда не перезаписывают файлы «на месте», а всегда дописывают новую версию «в конец», одновременно постепенно освобождая место от старых блоков «в начале». То есть такие ФС чем-то похожи на кольцевой буфер :). И такие ФС под linux есть, я их ещё раньше уже тестировал: ubifs, jffs2, yaffs, logfs, nilfs2… фиг кстати знает почему, но в прошлый раз я почему-то остановился на ubifs, хотя она (как и jffs2, и yaffs) предназначена для MTD (голой флеш-памяти, не блочных устройств) и монтировать её одно извращение, и после краша она ещё не восстанавливается потом.
</p><p>На самом деле из этих лучше брать nilfs2 — вроде самая живая и для блочных устройств подходит. Правда есть у неё как минимум один «нюанс» — на пустой ФС можно получить ошибку «нет свободного места», потому что она защищает (отказывается удалять) часть недавно созданных снапшотов. Время защиты вроде бы задаётся параметром `-o pp` при монтировании, но что-то я даже с pp=1 эту ошибку всё равно время от времени (при интенсивной записи) получал. Да и в общем в стабильность её работы у меня, честно говоря, особой веры нет. Экзотика, в общем.
</p><p>Ещё отдельный юмор — это самсунговская F2FS (Flash-Friendly FS). Фиг знает, в каком она месте friendly и зачем она вообще создана — случайную запись она не ускоряет вообще.
</p><p>Вот… некуда казалось бы податься любителю флешек. Но вчера возникла у меня идея — есть же btrfs! А в нём cow по дефолту для всех данных! Это ж как раз то, что нужно! И популярная, и по стабильности — не ext4, конечно, но я думаю уж точно получше экзотических nilfs’ов.
</p><p>И таки точно! Берём обычную флешку (5 мб/с скорость последовательной записи), бенчмаркаем случайное чтение+запись блоками по 4-16кб (с помощью fio, в 8 потоков). Получаем суммарно (чтение+запись):
</p>
<ul><li> ext4=7.15 iops</li>
<li> f2fs=7.38 iops</li>
<li> nilfs2=160.8 iops (лог-структурированная ФС)</li>
<li> btrfs=128 iops (круто, почти не хуже чем nilfs2)</li></ul>
<p>Короче всё, я на флешках буду btrfs теперь юзать.
</p>
https://yourcmc.ru/wiki/%D0%91%D0%BB%D0%BE%D0%B3:%D0%92%D0%B8%D1%82%D0%B0%D0%BB%D0%B8%D0%B9_%D0%A4%D0%B8%D0%BB%D0%B8%D0%BF%D0%BF%D0%BE%D0%B2/2016-08-27_%D0%9C%D0%B0%D1%82%D0%B5%D0%BC%D0%B0%D1%82%D0%B8%D1%87%D0%B5%D1%81%D0%BA%D0%BE%D0%B5_%D0%BD%D0%B0%D0%B1%D0%BB%D1%8E%D0%B4%D0%B5%D0%BD%D0%B8%D0%B5_%D0%BD%D0%B0_%D1%82%D0%B5%D0%BC%D1%83_MTBF_%D0%B8_AFRВиталий Филиппов — 2016-08-27 Математическое наблюдение на тему MTBF и AFRVitaliyFilippovhttps://yourcmc.ru/wiki/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:VitaliyFilippov2016-08-26T21:57:27Z2020-09-21T11:43:47Z<p>Есть такой параметр, заявляемый производителями жёстких дисков — MTBF (Mean Time Before Failure), среднее время наработки на отказ. Ясно, что он чисто маркетинговый, так как очевидно, что невозможно честно определить его для новой модели. И фигурируют там обычно миллионы часов, самое меньшее 800000 — аж 91 год с гаком.
</p><p>И вот непонятно — а какого чёрта харды вообще мрут при такой оценке надёжности? :-) ну как же, он 91 год в среднем прожить должен?
</p><p>Ответ кроется в математике. Есть более осмысленный параметр — AFR (Annualized Failure Rate), вероятность выхода из строя в течение года. По статистике Backblaze (кроме них никто её по ходу не публикует) реальный AFR у дисков Seagate и WD как минимум процентов 5-10, у некоторых «особо надёжных» моделей аж 25-28 %, и даже у дисков HGST не ниже 0,8 % (а в основном 1-1.5 %).
</p><p>А давайте попробуем по AFR посчитать MTBF? Если предположить, что AFR диска не меняется со временем, то <s>MTBF в годах = 1*(1-AFR) + 2*(1-AFR)² + 3*(1-AFR)³ + … (матожидание числа лет). Разворачиваем формулу дважды в сумму геометрической прогрессии (так как это по сути сумма геометрических прогрессий, начинающихся с 1… 2… 3… и т. п. членов), и получаем MTBF в годах = (1-AFR)/AFR². Можно записать это и наоборот, решив квадратное уравнение, и получить AFR = (-1 + sqrt(1+4*MTBF)) / (2*MTBF).
</p><p>По этой формуле MTBF 800000 часов = 9,93 % AFR, MTBF 1400000 часов = 7,6 % AFR, MTBF 2000000 часов = 6,4 % AFR. А 1 % AFR соответствует MTBF аж 86724000 часов! То есть, в принципе, MTBF 800000 часов не так уж и много, так как на самом деле он означает, что 10 % дисков выйдет из строя в первый же год :-).</s>
</p><p><s>Упс. В вычисления закралась досадная ошибка — правильная формула MTBF в годах = AFR + 1*AFR*(1-AFR) + 2*AFR*(1-AFR)² + 3*AFR*(1-AFR)³ + … = AFR + (1-AFR)/AFR. Соответственно AFR = (MTBF+1 — sqrt((MTBF+1)²-4)) / 2.</s>
</p><p>И, соответственно, никаких впечатляющих % там не будет — 800000 MTBF = 1.08% AFR, 1400000 MTBF = 0.62% AFR, 2000000 MTBF = 0.44% AFR. Ну ладно, тогда да, MTBF — просто ничего не значащая маркетинговая цифра :). Даже 1.08% — <s>абсолютно нереально</s> реально, современные HGST так и живут. Но когда я это писал, было таки нереально.
</p><p>UPD: Вторая версия формулы, по-моему, тоже была неправильной, но, что удивительно, численные результаты получились верными. Правильно так:
</p>
<pre>
MTBF = 1*AFR*(1-AFR) + 2*AFR*(1-AFR)^2 + ... = Sum_{i=0..+inf}((1-AFR) * (1-AFR)^i) = (1-AFR) / AFR
1 - AFR = MTBF * AFR <=> AFR = 1/(1+MTBF)
</pre>
<p>По этой формуле MTBF 800000 часов = 1.08% AFR, MTBF 1400000 часов = 0.62% AFR, MTBF 2000000 часов = 0.44% AFR.
</p><p>А, и ещё картина по идее может зависеть от распределения отказов — интуиция подсказывает, что вряд ли оно равномерное. Но сильно, наверное, это вряд ли повлияет, так как вот тут <a rel="nofollow" class="external free" href="http://www.cs.cmu.edu/~bianca/fast/">http://www.cs.cmu.edu/~bianca/fast/</a> есть статья, из которой видно, что, по-видимому, лет где-то до 5 каждый год вероятность отказа неуклонно возрастает, а потом даже немного снижается.
</p><p><br />
</p>
https://yourcmc.ru/wiki/%D0%91%D0%BB%D0%BE%D0%B3:%D0%92%D0%B8%D1%82%D0%B0%D0%BB%D0%B8%D0%B9_%D0%A4%D0%B8%D0%BB%D0%B8%D0%BF%D0%BF%D0%BE%D0%B2/2016-08-21_%D0%9F%D0%B0%D1%82%D1%82%D0%B5%D1%80%D0%BD_%D0%B1%D1%8D%D0%B4_%D0%B1%D0%BB%D0%BE%D0%BA%D0%BE%D0%B2_%D0%B2_ddrescueviewВиталий Филиппов — 2016-08-21 Паттерн бэд блоков в ddrescueviewVitaliyFilippovhttps://yourcmc.ru/wiki/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:VitaliyFilippov2016-08-21T14:10:22Z2016-08-21T14:19:38Z<p>Короче прогнал ddrescue на своём сдохшем Seagate Constellation ES.3 3 тб (ST3000NM0033). Вот такая картина (ddrescueview):
</p><p><a href="https://yourcmc.ru/wiki/%D0%A4%D0%B0%D0%B9%D0%BB:Ddrescue1.png" class="image"><img alt="Ddrescue1.png" src="https://yourcmc.ru/wiki/images/thumb/7/7d/Ddrescue1.png/600px-Ddrescue1.png" width="600" height="298" srcset="https://yourcmc.ru/wiki/images/thumb/7/7d/Ddrescue1.png/900px-Ddrescue1.png 1.5x, https://yourcmc.ru/wiki/images/thumb/7/7d/Ddrescue1.png/1200px-Ddrescue1.png 2x" /></a>
</p><p>Если поближе, то вот:
</p><p><a href="https://yourcmc.ru/wiki/%D0%A4%D0%B0%D0%B9%D0%BB:Ddrescue2.png" class="image"><img alt="Ddrescue2.png" src="https://yourcmc.ru/wiki/images/thumb/d/d0/Ddrescue2.png/600px-Ddrescue2.png" width="600" height="298" srcset="https://yourcmc.ru/wiki/images/thumb/d/d0/Ddrescue2.png/900px-Ddrescue2.png 1.5x, https://yourcmc.ru/wiki/images/thumb/d/d0/Ddrescue2.png/1200px-Ddrescue2.png 2x" /></a>
</p><p>О чём нам говорит такой паттерн? Судя по всему, об одной полностью сдохшей головке. Если посмотреть на цифры, то становится чётко видно, что картина по всему диску следующая — в начале диска идёт 50мб читаемых, 50мб нечитаемых, потом 600мб читаемых, потом примерно 50мб нечитаемых, 100мб читаемых, 50мб нечитаемых и дальше так и повторяется — 600-50-100-50… 600мб ближе к концу диска (к центру пластин), на самом деле, превращается в ~265мб, но соотношение всё время сохраняется чётко — 12:1:2:1 (где-то 11.8, где-то 12.2, но суть одна).
</p><p>Блина у этой модели 4, головок 8. Потеряна как раз 1/8 данных. Логично, что это как раз и должно означать мёртвую головку. Единственным непонятным для меня моментом был паттерн — я думал, раз головок 8, хард с них должен читать по порядку — 12345678 12345678 и т. п. Но тогда картина читаемых-нечитаемых областей выглядела бы как 7-1-7-1-7-1…, а не 12-1-2-1-12-1-2-1…, как у меня.
</p><p>Ответ, оказывается, простой — вместо традиционной схемы диски сейчас применяют также схемы «Cylinder Serpentine», «Surface serpentine» и их комбинации. В моём случае это как раз «Cylinder serpentine»: 12345678 87654321 12345678
87654321…, и плохая тут, видимо, как раз 2-я головка: 1(2)345678876543(2)11(2)345678876543(2)1…
</p><p>Такой вот получился «RAID 0» из одного диска — сдохла одна головка, а потеряется почти всё, так как все данные дырявые, максимальный размер неповреждённой области — 614 мб.
</p><p>Интересные ссылки по теме:
</p>
<ul><li> <a rel="nofollow" class="external text" href="http://hddscan.com/doc/HDD_Tracks_and_Zones.html">HDD from inside: Tracks and Zones. How hard it can be?</a></li>
<li> <a rel="nofollow" class="external text" href="http://www.esos.hanyang.ac.kr/files/publication/conferences/international/Dig%20-%20Rapid%20Characterization%20of%20Modern%20Hard%20Disk%20Drive%20and%20its%20performance%20implication.pdf">DIG: Rapid Characterization of Modern Hard Disk Drive and its performance implication</a>, <a rel="nofollow" class="external text" href="https://sourceforge.net/projects/digmodernharddi/">исходники инструмента анализа из статьи</a></li></ul>
https://yourcmc.ru/wiki/%D0%91%D0%BB%D0%BE%D0%B3:%D0%92%D0%B8%D1%82%D0%B0%D0%BB%D0%B8%D0%B9_%D0%A4%D0%B8%D0%BB%D0%B8%D0%BF%D0%BF%D0%BE%D0%B2/2016-07-30_%D0%9A%D0%BE%D1%80%D0%BF%D1%83%D1%81_Aerocool_-_%D0%BD%D0%B0%D0%B5%D0%B4%D0%B0%D0%BB%D0%BE%D0%B2%D0%BEВиталий Филиппов — 2016-07-30 Корпус Aerocool - наедаловоVitaliyFilippovhttps://yourcmc.ru/wiki/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:VitaliyFilippov2016-07-29T21:44:46Z2016-07-29T21:44:47Z<p>Твою мать! Козлы! <a rel="nofollow" class="external free" href="https://market.yandex.ru/product/9275336">https://market.yandex.ru/product/9275336</a>, <a rel="nofollow" class="external free" href="https://market.yandex.ru/product/9275333">https://market.yandex.ru/product/9275333</a> - написано, что безвинтовое крепление HDD, в отзывах кто-то подтверждает — да, безвинтовое крепление, да, удобно.
</p><p>А там оно не то что безвинтовое! Там и винтового-то не очень! Схема крепления через дикую жопу. Какие салазки, вы о чём! Крепления хардов просто какой-то суперизвращенец придумывал:
</p>
<ul><li> два 3.5" в самом низу на винтах, вставляются со стороны материнки.</li>
<li> один 2.5" плашмя на отведённом месте + с ОДНОЙ стороны крепится винтами.</li>
<li> один 2.5" аж вертикально, крепится к панели внутри корпуса 4 винтами.</li>
<li> один 3.5" плашмя на отведённом месте под 5.25" отсеками и крепится винтами.</li>
<li> и один 3.5" прикручивается к специальной 5.25" панельке-переходнику, к ней же по желанию под хард лепится доп.вентилятор (если докупишь) и этот страшный бутерброд ставится в 5.25" отсек.</li></ul>
<p>И ещё остаётся пара свободных 5.25" отсеков (нафиг они вообще нужны в 21 веке). ЖЕСТЬ.
</p><p>Повёлся блин на описание товара. Заказал, теперь возвращать буду.
</p>
https://yourcmc.ru/wiki/%D0%91%D0%BB%D0%BE%D0%B3:%D0%92%D0%B8%D1%82%D0%B0%D0%BB%D0%B8%D0%B9_%D0%A4%D0%B8%D0%BB%D0%B8%D0%BF%D0%BF%D0%BE%D0%B2/2016-07-21_%D0%9E%D0%BF%D0%B0!_%D0%92_%D1%81%D0%B2%D1%8F%D0%B7%D0%B8_%D1%81_%D0%B7%D0%B0%D0%BA%D0%BE%D0%BD%D0%BE%D0%BC_%D0%BE_%D0%BF%D0%B5%D1%80%D1%81_%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85_Seagate_%D0%B3%D0%B0%D1%80%D0%B0%D0%BD%D1%82%D0%B8%D0%B8_%D0%B1%D0%BE%D0%BB%D1%8C%D1%88%D0%B5_%D0%BD%D0%B5%D1%82Виталий Филиппов — 2016-07-21 Опа! В связи с законом о перс данных Seagate гарантии больше нетVitaliyFilippovhttps://yourcmc.ru/wiki/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:VitaliyFilippov2016-07-21T13:34:40Z2016-07-21T13:34:41Z<p>За#бцааааа…
</p><p>Гарантия производителя на диски Seagate Constellation ES.3 — 5 лет, но похоже, что теперь в связи с законом о персональных данных ей невозможно воспользоваться: <a rel="nofollow" class="external free" href="http://www.seagate.com/ru/ru/support/russia-law/">http://www.seagate.com/ru/ru/support/russia-law/</a>
</p><p>Типа мы же иностранная компания, гарантийные запросы обрабатываем за рубежом. А они включают персональные данные.)). запретили обрабатывать персональные данные — вот и идите со своей гарантией <s>в жопу</s> в магазин, где покупали. :-))
</p><p>Это у меня такой хард дуба дал. производство 2013, купил либо в 2013, либо в 2014, гарантия в магазинах обычно года 2-3, но главное чек не могу найти и не помню где брал…
</p>
https://yourcmc.ru/wiki/%D0%91%D0%BB%D0%BE%D0%B3:%D0%92%D0%B8%D1%82%D0%B0%D0%BB%D0%B8%D0%B9_%D0%A4%D0%B8%D0%BB%D0%B8%D0%BF%D0%BF%D0%BE%D0%B2/2016-07-21_Helvetica_Neue_CondensedВиталий Филиппов — 2016-07-21 Helvetica Neue CondensedVitaliyFilippovhttps://yourcmc.ru/wiki/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:VitaliyFilippov2016-07-21T12:35:43Z2016-07-21T12:38:51Z<p>Всегда считал, что Helvetica — это тот же Arial, а так как Arial не люблю, считал, что и Helvetica — отстой. Потом, правда, понял, что в мелких размерах Arial выглядит неплохо, но уже было не важно).
</p><p>А недавно открыл для себя, что Helvetica Neue ещё бывает Condensed и вот это классный шрифт. Правда, в теории платный, но <s>кого ж это волнует</s> на самом деле, он настолько похож на свободный Roboto Condensed, что фактически можно юзать его (хотя субъективно гельветика чуть поаккуратней). Ещё один похожий шрифт — PT Sans Narrow (но он-то точно покривей). Вот все три:
</p><p><a href="https://yourcmc.ru/wiki/%D0%A4%D0%B0%D0%B9%D0%BB:Condensed.png" class="image"><img alt="Condensed.png" src="https://yourcmc.ru/wiki/images/3/33/Condensed.png" width="600" height="216" /></a>
</p><p><br />
Посередине Helvetica, сверху Roboto, внизу PT Sans.
</p>
https://yourcmc.ru/wiki/%D0%91%D0%BB%D0%BE%D0%B3:%D0%92%D0%B8%D1%82%D0%B0%D0%BB%D0%B8%D0%B9_%D0%A4%D0%B8%D0%BB%D0%B8%D0%BF%D0%BF%D0%BE%D0%B2/2016-06-27_%D0%9C%D0%B8%D0%BD%D1%83%D1%82%D0%BA%D0%B0_%D1%8E%D0%BC%D0%BE%D1%80%D0%B0_nodejsВиталий Филиппов — 2016-06-27 Минутка юмора nodejsVitaliyFilippovhttps://yourcmc.ru/wiki/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:VitaliyFilippov2016-06-27T09:42:24Z2016-06-27T09:42:25Z<p>Задача: вытащить часть пути до первой части, содержащей glob-паттерн (glob — это стандартные шаблоны имён файлов: * ? [] {}).
</p><p>Решение: один регэксп, да? Нееееет!
</p><p>Для node.js есть целая библиотека <a rel="nofollow" class="external text" href="https://www.npmjs.com/package/glob-parent">glob-parent</a>. Очень содержательная:
</p>
<pre class="javascript"><span style="color: #000066; font-weight: bold;">var</span> path <span style="color: #339933;">=</span> require<span style="color: #009900;">(</span><span style="color: #3366CC;">'path'</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span>
<span style="color: #000066; font-weight: bold;">var</span> isglob <span style="color: #339933;">=</span> require<span style="color: #009900;">(</span><span style="color: #3366CC;">'is-glob'</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span>
 
module.<span style="color: #660066;">exports</span> <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">function</span> globParent<span style="color: #009900;">(</span>str<span style="color: #009900;">)</span> <span style="color: #009900;">{</span>
str <span style="color: #339933;">+=</span> <span style="color: #3366CC;">'a'</span><span style="color: #339933;">;</span> <span style="color: #006600; font-style: italic;">// preserves full path in case of trailing path separator</span>
<span style="color: #000066; font-weight: bold;">do</span> <span style="color: #009900;">{</span>str <span style="color: #339933;">=</span> path.<span style="color: #660066;">dirname</span><span style="color: #009900;">(</span>str<span style="color: #009900;">)</span><span style="color: #009900;">}</span> while <span style="color: #009900;">(</span>isglob<span style="color: #009900;">(</span>str<span style="color: #009900;">)</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span>
<span style="color: #000066; font-weight: bold;">return</span> str<span style="color: #339933;">;</span>
<span style="color: #009900;">}</span><span style="color: #339933;">;</span></pre>
<p>Не, ну наверно там парсинг сложный, да? Давайте посмотрим, как написан <a rel="nofollow" class="external text" href="https://github.com/jonschlinkert/is-glob">is-glob</a>:
</p>
<pre class="javascript"><span style="color: #000066; font-weight: bold;">var</span> isExtglob <span style="color: #339933;">=</span> require<span style="color: #009900;">(</span><span style="color: #3366CC;">'is-extglob'</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span>
 
module.<span style="color: #660066;">exports</span> <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">function</span> isGlob<span style="color: #009900;">(</span>str<span style="color: #009900;">)</span> <span style="color: #009900;">{</span>
<span style="color: #000066; font-weight: bold;">return</span> <span style="color: #000066; font-weight: bold;">typeof</span> str <span style="color: #339933;">===</span> <span style="color: #3366CC;">'string'</span>
<span style="color: #339933;">&&</span> <span style="color: #009900;">(</span><span style="color: #009966; font-style: italic;">/[*!?{}(|)[\]]/</span>.<span style="color: #660066;">test</span><span style="color: #009900;">(</span>str<span style="color: #009900;">)</span>
<span style="color: #339933;">||</span> isExtglob<span style="color: #009900;">(</span>str<span style="color: #009900;">)</span><span style="color: #009900;">)</span><span style="color: #339933;">;</span>
<span style="color: #009900;">}</span><span style="color: #339933;">;</span></pre>
<p>Гм. Ну что ж, может вся хитрость в <a rel="nofollow" class="external text" href="https://github.com/jonschlinkert/is-extglob">is-extglob</a>?
</p>
<pre class="javascript">module.<span style="color: #660066;">exports</span> <span style="color: #339933;">=</span> <span style="color: #000066; font-weight: bold;">function</span> isExtglob<span style="color: #009900;">(</span>str<span style="color: #009900;">)</span> <span style="color: #009900;">{</span>
<span style="color: #000066; font-weight: bold;">return</span> <span style="color: #000066; font-weight: bold;">typeof</span> str <span style="color: #339933;">===</span> <span style="color: #3366CC;">'string'</span>
<span style="color: #339933;">&&</span> <span style="color: #009966; font-style: italic;">/[@?!+*]\(/</span>.<span style="color: #660066;">test</span><span style="color: #009900;">(</span>str<span style="color: #009900;">)</span><span style="color: #339933;">;</span>
<span style="color: #009900;">}</span><span style="color: #339933;">;</span></pre>
<p>Это весь код этих 3-х библиотек, ну за исключением всяких README и package.json, конечно… которые там в 5 раз больше.
</p><p><a href="https://yourcmc.ru/wiki/%D0%A4%D0%B0%D0%B9%D0%BB:Alice-facepalm.jpg" class="image"><img alt="Alice-facepalm.jpg" src="https://yourcmc.ru/wiki/images/c/c6/Alice-facepalm.jpg" width="500" height="275" /></a>
</p>
https://yourcmc.ru/wiki/%D0%91%D0%BB%D0%BE%D0%B3:%D0%92%D0%B8%D1%82%D0%B0%D0%BB%D0%B8%D0%B9_%D0%A4%D0%B8%D0%BB%D0%B8%D0%BF%D0%BF%D0%BE%D0%B2/2016-06-16_ClickHouseВиталий Филиппов — 2016-06-16 ClickHouseVitaliyFilippovhttps://yourcmc.ru/wiki/%D0%A3%D1%87%D0%B0%D1%81%D1%82%D0%BD%D0%B8%D0%BA:VitaliyFilippov2016-06-16T09:39:40Z2016-06-16T09:39:41Z<p>ВАУ! ЖИР!
</p><p>Яндекс сделал опенсорсную столбцовую СУБД! <a rel="nofollow" class="external text" href="https://clickhouse.yandex/">ClickHouse</a>.
</p><p><a rel="nofollow" class="external free" href="https://github.com/yandex/ClickHouse">https://github.com/yandex/ClickHouse</a>
</p><p><a rel="nofollow" class="external free" href="https://habrahabr.ru/company/yandex/blog/303282/">https://habrahabr.ru/company/yandex/blog/303282/</a>
</p>