Хорошая стратегия, плохая стратегия. В чем отличие и почему это важно • Ричард Румельт • 2011
Большинство стратегий — мусор. Не потому что люди тупые, а потому что их научили путать цели с планом. «Хочу миллиард» — это не стратегия. «Как я отберу рынок у того, кто дешевле и быстрее» — вот это стратегия. Румельт разжёвывает разницу без соплей и с примерами из армии, бизнеса и NASA.
Стратегия — это ответ на вызов, а не список целей
Цель — «стать лидером». Стратегия — «что именно мешает и как это обойти». Если в твоём документе нет препятствия, которое надо перепрыгнуть, это не стратегия. Это вишлист. Румельт говорит прямо: хорошая стратегия начинается с признания, что всё плохо, и с поиска узкого места, которое решает исход.
Плохая стратегия пахнет пустословием
Четыре признака: пустословие (умные слова без смысла), игнорирование вызова (делаем вид, что проблемы нет), подмена целей стратегией («наша цель — расти»), кривые подцели (делаем не то, что нужно). Если твой план звучит как «синергия инноваций для устойчивого роста» — это не план. Это корпоративная мантра.
Ядро: диагноз, политика, действия
Хорошая стратегия — не поэма. Это три части. Диагноз: что реально происходит. Направляющая политика: общий подход к преодолению препятствия. Согласованные действия: шаги, которые работают только вместе. Без любого элемента конструкция разваливается. Диагноз без действий — нытьё. Действия без диагноза — хаос. Политика без них обоих — лозунг.
Диагноз — это упрощение, а не описание
Хороший диагноз не перечисляет сорок симптомов. Он вычленяет главное. Как врач: не «у вас температура и кашель», а «у вас пневмония, вот почему». Если диагноз не режет сложность до одной-двух ключевых точек, ты не понял ситуацию. Ты просто пересказал её.
Направляющая политика — это правило, а не расписание
Это рамка, которая отсекает лишнее. «Мы не играем в премиум, мы давим ценой». «Мы не лезем в город, мы работаем в пригороде». Всё, что не вписывается — мимо. Политика задаёт направление, но не диктует каждый шаг. Она говорит «да» и «нет» без объяснений. Если её нельзя применить к конкретному решению за секунду — это не политика, а трёп.
Проксимальные цели: близко, больно, достижимо
Не «захватить мир». А «снизить отток на 5% за квартал». Румельт называет это проксимальными целями: они рядом, их можно потрогать, они дают энергию и фокусируют ресурсы. Далёкая цель мотивирует только в мотивационном ролике. Близкая цель заставляет вставать утром.
Сила — в рычаге, фокусе и инерции
Не надо быть сильнее всех. Надо найти точку, где малое усилие даёт большой результат. Или использовать чужую инерцию — конкурент не может развернуться быстро, а ты можешь. Или сфокусироваться на одном и вычистить всё остальное. Размазывать ресурсы — верный путь к нищете. Это не мотивация. Это физика.
Любая хорошая стратегия обязательно имеет базовую логическую структуру, которую я называю «ядро». Состоит оно из трех элементов: постановка диагноза, направляющая политика и согласованные действия. — Ричард Румельт
Как внедрить:
1. Выпиши главный вызов одной фразой. Не список проблем. Одну: «Мы теряем рынок, потому что…» Если не можешь — ты не понял ситуацию. Иди копай.
2. Сформулируй правило. Одно предложение, которое говорит «да» и «нет» без объяснений. Пример: «Мы не берём заказы дешевле X». Примерь к трём текущим решениям. Если не режет — перепиши.
3. Собери 3–5 действий, которые нельзя сделать по отдельности. Если они работают порознь — это не стратегия, а список задач. Выкинь лишнее.
Ноутбук засыпает, ноутбук просыпается, батарея «зависает» — более не отдает ни уровень заряда ни другие показатели, вне зависимости от подключения к сети.
Патч ядра Linux и три года изысканий, рассказываю как это было.
Божественные Вайнона Райдер и Натали Портман, работы нейросети. Ну и пропатченное ядро.
Вводная
Автор очень давно использует самые разнообразные версии и вариации Linux и UNIX‑систем для работы и диких развлечений, в том числе на ноутбуках, поэтому старается решать все найденные проблемы, по мере сил.
Временами проблема возвращается заново в новых версиях ядра, будучи решенной в прошлом, временами происходит наоборот и проблема проявляется только в самых свежих версиях Linux.
Бывает приходится приостановить поиски решения и вернуться к изысканиям спустя много лет, когда случайно обнаруживается новый вариант решения.
Описываемая история — как раз из последних.
Проблема
Вкратце проблема заключалась в абзаце, вынесенном в заголовок:
ноутбук засыпает, ноутбук просыпается, после чего батарея «зависает» — более не отдает свой актуальный уровень заряда и все показатели, вне зависимости от подключения к электросети.
Естественно в Windows все работало правильно и стабильно, в любых режимах засыпания.
Ноутбук редкий, ноутбук старый, от вендора, который в гробу видал никогда не любил альтернативные ОС и тем более в страшном сне не мог представить, что одна из его топовых моделей (на свое время) вместо подсчета прибылей успешному бизнесмену, стала бы использоваться для компиляции ядра из исходников и прочих гиковских непотребств.
Никакая отладка ядра и никакие отладочные сообщения не помогли, что неудивительно:
Работа с ACPI — традиционно самая замороченная область ядра Linux, а процессы засыпания и возвращения к работе — сложны и нестабильны по своей сути.
Так что оно глючило, глючит и будет глючить, в любой ОС и на любом оборудовании при любой погоде.
Процесс отлова ошибок связанных с ACPI усложнен тем, что такие ошибки чаще всего «плавающие» — могут появиться не через один цикл «засыпания‑пробуждения» а например через десять, т. е. вам надо десять раз подряд погрузить ноутбук в сон и затем пробудить чтобы отловить ошибку.
Правда ведь отладка это весело?
Решение
Далеко не сразу (ушло примерно три года), путем хитрых запросов к поисковикам и изучения исходников ядра, автор все же смог отыскать концы этой проблемы.
Description : I tracked the issue ,I discovered that all was working good until the 4.19.86 kernel.
So I checked DIFF and After many tries maybe 50 or more.
I found the cause : It was (if statement was added in 4.19.86 COMMIT) ,particularly checking if spaceid == 0 [ACPI_ADR_SPACE_SYSTEM_MEMORY]. Commit Link
Разумеется патч китайского автора оказался нерабочий, сообщение было написано про другую модель ноутбука, с другим поведением при сбое и с неверной фиксацией на типе батареи в качестве источника проблемы.
Еще речь шла про совсем уж древнюю версию ядра (4.19, релиз в 2018м году) а само сообщение датировалось 2022 годом.
Но вы ведь и не думали, что все будет настолько просто, верно?
/* * These address spaces do not need a call to _REG, since the ACPI * specification defines them as: "must always be accessible". Since * they never change state (never become unavailable), no need to ever * call _REG on them. Also, a data_table is not a "real" address space, * so do not call _REG. September 2018. */
Обратите внимание на дату — 2018й год, год выпуска версии ядра 4.19, в которой и проявилась данная проблема.
По сути самого комментария и исходя из логики, один из коммитеров ядра Linux в далеком 2018 году хотел «сделать как лучше»:
Полагая что строгое соотвествие спецификации ACPI в данном случае бывает всегда — коммитер вставил заглушку, убирающую вызов _REG метода для вроде как системных частей ACPI‑прошивки.
Чем и поломал восстановление статуса батареи при пробуждении ноутбука.
Благими намерениями выстелена дорога в Ад. (ц)
Исправление
Все что нужно сделать для исправления ситуации, это убрать из условия проверки константу ACPI_ADR_SPACE_SYSTEM_MEMORY:
Ну и опционально добавить отладку, чтобы убедиться в правильности работы:
if (space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) { printk(KERN_DEBUG "PRO HEHE : Bypassing for battery is done"); }
Отладка была включена в текущем ядре, само сообщение можно наблюдать на стартовой картинке к статье.
Для того чтобы убедиться в правильности работы, достаточно усыпить ноутбук, пробудить и подергать состояние батареи несколько раз:
Эпилог
Такой патч никогда не примут в аппстрим ядра, потому что он неправилен с точки зрения спецификации ACPI.
Собственно сама проблема с зависшей батареей появилась из-за того что некоторые вендоры класть хотели на стандарты и спецификации.
К сожалению такого рода проблемы в новых версиях ядра Linux появляются все чаще, поэтому и ситуация и ее решение — уже можно сказать типовые и подобным образом решаются ныне и многие другие проблемы с оборудованием.
Так что если на вашем ноутбуке также проявляется описанная проблема с «зависанием» батареи — теперь будете знать в какую сторону копать.
P.S.
Если вы внимательно смотрели на заглавную картинку к статье, могли заметить что автор использовал нестандартное ядро:
XanMod is a general-purpose Linux kernel distribution with custom settings and new features. Built to provide a stable, smooth and solid system experience.
The real-time version is recommended for critical runtime applications such as Linux gaming server / client for eSports, streaming, live productions and ultra-low latency enthusiasts.
Этот набор патчей ядра Linux действительно сильно ускоряет работу, что особенно заметно на некрожелезе времен молодости Брежнева, которое автор регулярно использует для укрепления стойкости духа.
P.P.S.
На данный момент проблема все также актуальна и вряд ли будет решена в апстриме ядра в обозримом будущем. Поэтому автор продолжает накладывать описанный патч (и еще несколько) при каждой пересборке ядра.
Если вам неудержимо хочется использовать оборудование из музея для современной разработки — статья специально для вас.
Машины должны служить а не требовать ресурсы. И автор патча l9 об этом знает.
Эпический баг
Сейчас наверное некоторые читатели сильно удивятся:
с 2007 года в ядре Linux живет серьезный баг, приводящий к полному зависанию системы при работе под большой нагрузкой на память.
На дворе на момент написания статьи май 2025 года, так что баг успел отпраздновать совершеннолетие и открыть первую бутылку пива.
Оригинальный репорт выглядит так:
Разумеется разработчики ядра в курсе проблемы, но по ряду причин.. не считают этот баг важным.
Да, вы правильно прочитали:
«полное зависание системы под нагрузкой» и «разработчики не считают важным исправлять» — как вам такие реалии Linux?
Более того, недавно тикет с описанием этого бага вообще закрыли с эпической формулировкой «just become obsolete»:
С легким намеком, что некоторым стоит перестать собирать себе компьютеры по помойкам:
but now I don't bother with less than 32Gb of RAM for a desktop.
Теперь прокрутите обсуждение бага в трекере вниз и посмотрите на последнее сообщение о проблеме:
Специально сохранил картинкой для истории, вдруг не поверите.
Оно конечно все замечательно и у самого автора этой статьи давно 64Гб на одной из рабочих машин, а некоторые коллеги успели впихнуть даже 128Гб, причем в ноутбук — чтобы мы наконец увидели SUSE Linux, которая не тормозит.
Но к сожалению одними любителями компьютерного антиквариата данная проблема не ограничивается — на нынешние облачные времена типичное рабочее окружение Linux это виртуальная машина, с ограниченным обьемом памяти. Скорее всего даже ваш корпоративный сайт крутится на виртуальной машине с 4Гб памяти.
Так что на самом деле проблема касается практически всех пользователей Linux, а не только идейных нищебродов энтузиастов, собирающих себе оборудование по музеям.
Как так получилось
Если вы хоть немного понимаете в компьютерах, прочитав абзац выше и сопоставив масштаб проблемы и отношение к ней разработчиков Linux, думаю уже сделали определенные выводы:
либо команда разработки ядра Linux — поголовно некомпетентны, либо у автора контракт с рептилоидами в описании выше был упущен ряд важных нюансов.
Правда как обычно где‑то между — «особенных» среди современных разработчиков Linux действительно хватает, но ряд нюансов я все же намеренно упустил.
Опишу в какой момент проявляется этот баг:
надо долго и упорно увеличивать нагрузку на использование памяти, причем маленькими порциями и обязательно из нескольких разных процессов — чтобы OOM Killer не успел отработать.
На практике надо либо заниматься тренировкой нейросетей, либо непрерывно гонять тяжелые приложения на Java/Node (в первую очередь IDE) и постоянно запускать сборку больших проектов.
И все это на неподготовленном офисном оборудовании с 4-6 Гб памяти, представляющем историческую ценность, либо в виртуальной машине.
Патч l9ec
Уже давно существует неофициальный патч, решающий описанную проблему с зависанием квадратно-гнездовым радикальным способом:
The kernel does not provide a way to protect the working set under memory pressure. A certain amount of anonymous and clean file pages is required by the userspace for normal operation. First of all, the userspace needs a cache of shared libraries and executable binaries. If the amount of the clean file pages falls below a certain level, then thrashing and even livelock can take place.
По сути этим патчем формируется небольшой объем памяти (тот самый working set), которую запрещается перегружать даже самым хитрым приложениям, откусывающим память по килобайтам.
Разумеется патч заметили и тут находится архив эпической переписки в рассылке Linux Kernel длиною в год, где автор патча пытается объяснить окружающим что он не верблюд и проблема действительно есть.
Однако патч в мейнстрим так и не попал, что наводит на определенные нехорошие мысли.
История с Xanmod
Помимо основной версии ядра т. н. «vanilla», исходники которого выкладываются на широко известном kernel.org, существуют «васянские сборки» — наборы патчей ядра, собранные энтузиастами под конкретную задачу.
Одна из таких сборок называется Xanmod и посвящена работе современного ядра на desktop-системе с минимальными визуальными задержками:
XanMod is a general-purpose Linux kernel distribution with custom settings and new features. Built to provide a stable, smooth and solid system experience.
Так вот на момент появления l9ec патча, он был включен в сборку Xanmod:
Но в последних 6.х версиях Xanmod его уже нет, на что есть формальная причина — появление вот этого патча, вроде как окончательно решающего проблему c зависанием:
На данный момент MGLRU в mainline и скорее всего работает прямо сейчас и у вас в системе, если конечно у вас современный линукс и MGLRU не отключен вручную.
К сожалению принцип работы MGLRU другой (см. комментарий выше про 32Гб памяти на десктопе) и тестировался его функционал тоже в другом месте:
On Android, our most advanced simulation that generates memory pressure from realistic user behavior shows 18% fewer low-memory kills, which in turn reduces cold starts by 16%.
Как нетрудно догадаться, «realistic user behavior» на мобильном Android несколько отличается от тотальной перегрузки тяжелыми средствами разработки на дохлом десктопе или еще более слабой виртуальной машине.
Поэтому «продвинутым пользователям Linux» в очередной раз придется заботиться о себе и своих проблемах самостоятельно.
Эта история — еще одна причина, по которой стоит использовать *BSD. Реклама.
Портирование на 6.х ядро
К сожалению автор патча l9 видимо устав бодаться с идиотами, не стал переносить свой замечательный патч в 6.х ветку ядра, решив что раз более умные ребята из Google выкатили MGLRU — от его решения толку больше не будет.
Как ни странно, но это не так и l9 патч куда более предсказуем и надежен как удар ломом, в отличие от цирка с аж 14 патчами MGLRU:
These initial multi-generational LRU patches amount to 14 patches at the moment and in a patched kernel can be enabled via the LRU_GEN Kconfig switch
Собственно эта статья появилась на свет после того как автор опять словил зависание под нагрузкой во время работы над большим проектом, из-за чего и решил откопать дедовский пулемет портировать известный патч в 6.х ядро.
За основу был взят последний патч для 5.х ветки без учета MGLRU: le9ec-5.15.patch а его логика добавлялась в Xanmod-версию ядра 6.14.5.
Ниже по шагам объясняю как выполнить перенос логики патча, чтобы процедуру можно было повторить и на более новых ядрах и на «vanilla» версиях.
Скачиваем архив с Xanmod ядром и l9-патч по ссылкам выше и распаковываем.
Стоит сразу предупредить, что размер текущей версии ядра Linux в распакованном виде ~1.8 Гигабайт, а для сборки понадобится еще ~28 Гигабайт.
Вот такие нынче ядра.
Разумеется применить готовый diff автоматически для ветки 6.х не получится, так что будем переносить логику патча по шагам.
Всего в рамках патча изменения происходят в пяти файлах:
Поскольку исправлять документацию нам не очень актуально, первый файл можно пропустить. Таким образом первое актуальное исправление находится в файле include/linux/mm.h, куда добавляются глобальные переменные, отвечающие за настраиваемые лимиты:
Все что нужно сделать — вставить строки в файл include/linux/mm.h:
/* * Force-scan anon if clean file pages is under vm.clean_low_kbytes * or vm.clean_min_kbytes. */ if (sc->clean_below_low || sc->clean_below_min) { scan_balance = SCAN_ANON; goto out; }
Следующая правка в этом же файле должна быть вставлена в этот же метод get_scan_count, но ниже по коду — ориентируйтесь на строку nr[lru] = scan;благо она такая одна:
Я вставил логику проверки сразу над ней:
/* * Hard protection of the working set. */ if (file) { /* * Don't reclaim file pages when the amount of * clean file pages is below vm.clean_min_kbytes. */ if (sc->clean_below_min) scan = 0; } else { /* * Don't reclaim anonymous pages when their * amount is below vm.anon_min_kbytes. */ if (sc->anon_below_min) scan = 0; } nr[lru] = scan;
Следующей правкой добавляется новая функция prepare_workingset_protection, которая должна вызываться из существующего метода shrink_node_memcgs:
Так что вам надо найти функцию shrink_node_memcgs (она такая одна) и вставить новую функцию prepare_workingset_protection над ней:
static void prepare_workingset_protection(pg_data_t*pgdat, struct scan_control *sc) { /* * Check the number of anonymous pages to protect them from * reclaiming if their amount is below the specified. */ if (sysctl_anon_min_kbytes) { unsignedlong reclaimable_anon;
/* * Check the number of clean file pages to protect them from * reclaiming if their amount is below the specified. */ if (sysctl_clean_low_kbytes || sysctl_clean_min_kbytes) { unsignedlong reclaimable_file, dirty, clean;
reclaimable_file = node_page_state(pgdat, NR_ACTIVE_FILE) + node_page_state(pgdat, NR_INACTIVE_FILE) + node_page_state(pgdat, NR_ISOLATED_FILE); dirty = node_page_state(pgdat, NR_FILE_DIRTY); /* * node_page_state() sum can go out of sync since * all the values are not read at once. */ if (likely(reclaimable_file > dirty)) clean = (reclaimable_file - dirty) << (PAGE_SHIFT - 10); else clean = 0;
Собственно последняя правка это вызов новой функции из существующей shrink_node_memcgs:
После внесения всех этих исправлений, запускаем один из вариантов настройки ядра:
make xconfig
И наблюдаем новые поля настройки:
Цепочка сборки и установки ядра совершенно стандартная:
make && make modules && make modules_install && make install
К сожалению это еще не все и прежде чем патч заработает надо будет отключить MGLRU, который как я уже описывал — успели внести в основную ветку ядра:
cat /sys/kernel/mm/lru_gen/enabled
Должен показать 0x0007 если MGLRU включен, отключить можно командой:
echo 0 | sudo tee /sys/kernel/mm/lru_gen/enabled
Вот тут у автора патча лежат готовые скрипты для автоматизации всего этого цирка. Я же просто добавил строчку с отключением в /etc/rc.local.
Пруфы
Для тестов портированного патча, был взят один из моих боевых ноутбуков Lenovo Z580 2012го года выпуска, с 8Гб памяти:
На нем постоянно творится всевозможная дичь — тут пять разных операционных систем и куча проектов и инструментов для разработки на каждой.
Поэтому без особого труда были одновременно запущены:
PostgreSQL с реальной базой
MySQL тоже с реальной базой
Intellij Idea
VSCode
Сборка проекта на Node.js с Webpack и hot reload
Сборка достаточно крупного Java-проекта (~3000 исходных файлов)
Chromium с 20 вкладками
Напоминаю что все это на 8Гб реальной памяти и на ноутбукe. Причем в качестве ОС в этот раз была обычная Ubuntu:
Как-то так это выглядит в действии:
Через неделю после публикации я решил пойти еще дальше и поставил пропатченное с l9 ядро на ноутбук 2007 года с 3Гб памяти. И повторил тесты с нагрузкой. Видео тут.
Все более чем работает и пропатченное ядро замечательно отрабатывает свою пайку.
Эпилог
Можно сколько угодно стебаться с пожеланиями «купи себе наконец нормальный компьютер», скажу что намеренно и давно использую старое железо — в первую очередь для оценки производительности создаваемого ПО.
И это одна из причин, по которой у нас получаются технические чудеса вроде Телепорты.
Если вы пока не дошли до столь глубокой стадии просвещения в разработке — все равно стоит знать, что мы ловили подобные зависания и в виртуальных машинах с Linux, например на CI‑сервере при сборке нескольких проектов одновременно.
Так что актуальность описанного все же высокая и как получилось, что столь простой и очевидный патч, который гарантированно решает проблему до сих пор не используют активно — ума не приложу. Ну и разумеется автору патча лучи респекта, благо это лучший представитель отечественной инженерной школы.
Статья была опубликована на Хабре, оригинал, в котором автор статьи себя не сдерживал и в красках рассказал все что думает о разработчиках ядра Linux как обычно можно найти в нашем блоге.
Всем Привет. Я давно об этом размышляю и решила записать свои мысли в эту гипотезу. Многие люди любят рассуждать о конце света или верить в параллельные вселенные, которые существуют прямо сейчас в других измерениях. Но если соединить физику ядра Земли, силу гравитации и законы эволюции, становится понятно, что всё устроено совершенно иначе. Наша Вселенная бессмертна, а параллельные миры просто не могут находиться с нами в одном времени из-за уникального устройства нашей планеты.
Всё начинается с физического фундамента Земли, а именно с силы, которая держит этот гигантский котел в равновесии. Наше ядро состоит из двух частей, где внешняя часть полностью жидкая и представляет собой расплавленный металл, а внутренняя является твердой из-за колоссального давления мантии и всей массы планеты. Гравитация выступает главной силой, которая крепко держит всю планету единым целым и удерживает нас на её поверхности. При этом мантия и земная кора - это лишь остывшая внешняя корка, сдерживающая кипящее металлическое сердце Земли. Но эта сложная система находится в хрупком балансе, и если в теории этот баланс нарушится, например от мощного внешнего космического удара, то ядро сработает как гигантский физический гейзер, из которого жидкий металл и магма под безумным давлением вырвутся струей наружу.
В этот момент начнется не окончательная смерть планеты, а масштабное обновление через лавовую перезагрузку. Раскаленное вещество ядра и мантии полностью растопит земную кору, и вся планета до единого сантиметра покроется бурлящей огненной магмой. Земля не умрет, она просто физически вернется в свое первоначальное состояние, в котором она была четыре с половиной миллиарда лет назад, когда только-только родилась в космосе и была точно таким же лавовым шаром. Именно здесь и запускается Эффект чистого холста, при котором вся старая ДНК полностью стирается под ноль. Любые следы нашей цивилизации, городов, интернета и генетического кода живых существ сгорают в глобальном океане магмы. Из-за этого становится очевидно, что параллельные вселенные, о которых говорят фантасты, на самом деле существовали последовательно во времени, а не одновременно с нами. До нашего цикла на Земле уже могли жить другие развитые существа с совершенно иной ДНК, но их мир закончился лавовой перезагрузкой, которая полностью вернула планету в состояние раскаленного эмбриона, навсегда освободив место для нас.
Однако Земля не может оставаться лавовым шаром вечно, поэтому со временем она снова начинает остывать, формируя твердую кору и воду, и на этой остывшей планете всё снова происходит заново. Из простых химических элементов непременно зародится новая первая клетка-предок в виде бактерии, и эволюция начнет свой ход с чистого листа по тем же самым рельсам развития от простого к сложному. Через миллионы лет на Земле снова появится разум, и это могут быть не люди, а совершенно другие существа, но они обязательно повторят наши ошибки из-за закона неизбежности опыта. Поскольку они будут жить на этой планете впервые, у них не будет нашей исторической памяти и наших учебников. Им придется самостоятельно и с нуля открывать законы физики, изобретать технологии, строить города и делить ресурсы. Из-за полного отсутствия опыта они будут наступать на те же самые грабли, через которые человечество проходит прямо сейчас, ведь сценарий развития разума один, и разумные существа in каждом новом цикле обречены проживать его заново. Конца света не существует, потому что жизнь невероятно упряма, а материя бессмертна, и финал нашего мира - это просто очищение холста и возвращение Земли к моменту своего рождения для создания новой истории.
Поделитесь своим мнением, интересно, что вы думаете по этому поводу.