О случайной сложности систем цепочки поставок
Современное вычислительное оборудование чрезвычайно мощное. Обычный смартфон способен выполнять миллиарды операций с плавающей запятой (FLOPS) в секунду и хранить сотни гигабайт данных. Один смартфон может технически запускать предиктивное распределение запасов для очень крупной розничной сети. Историческим данным потребуется соответствующее представление1, а для обработки данных придется использовать более легкие методы, такие как дифференцируемое программирование. Таким образом, системы цепочки поставок с высокой производительностью должны быть само собой разумеющимися. Конечно, компании могут позволить себе устройство чуть мощнее смартфона для управления и оптимизации своих цепочек поставок. Однако простое наблюдение за системами цепочки поставок наших клиентов в Lokad указывает на прямо противоположное: эти системы почти всегда работают медленно, и зачастую истошно так.

Современные лидеры в области программного обеспечения для цепочки поставок (ERP, WMS, MRP и т.д.) испытывают трудности с поддержкой даже 1 запроса в секунду на своем API-сервере. В Lokad мы ежедневно болезненно осознаем ужасающую производительность таких систем, поскольку находимся на передовой процесса извлечения данных. Для примерно дюжины клиентов первоначальное извлечение данных занимало почти месяц2. Медлительность различных API составляет 99,9% проблемы. Систем, способных обеспечивать 1 МБ/сек для извлечения данных, крайне мало. Еще реже встречаются системы, которые не заставляют нас без нужды повторно извлекать одни и те же данные снова и снова — чтобы получить максимально свежую информацию. Такие системы обычно располагают вычислительными ресурсами, число которых в 100 раз больше, чем было доступно 20 лет назад, и тем не менее, они не являются принципиально быстрее3 или выполняют задачи радикально лучше. Некоторые из самых прогрессивных поставщиков, использующих вычисления в памяти, требуют несколько терабайт ОЗУ для работы с розничными сетями, что является ужасающим4 объемом памяти, учитывая выполняемые задачи.
Эта «случайная сложность» многих (большинства?) систем цепочки поставок объясняется двумя основными причинами: во-первых, неправильными ожиданиями относительно прогресса самого вычислительного оборудования, во-вторых, отсутствием внимания к внутреннему дизайну решения.
Что касается прогресса вычислительного оборудования, то до недавнего времени не было ни одной (крупной) компании, в которой закон Мура не обсуждался десятками раз (обычно с ошибкой). Существовало ощущение, что компьютеры становятся нелепо быстрее с каждым днем. К сожалению, с начала 2000-х годов это утверждение перестало быть тривиально верным. Эта неправильная картина бесконечного прогресса привела многие компании-разработчики программного обеспечения, далеко выходящие за рамки цепочки поставок, к масштабным ошибкам. Многие проблемы, связанные с Windows Vista (выпущенной в 2006 году), можно проследить до первоначальных ожиданий — еще в 2001 году, когда была выпущена Windows XP — от инженеров Microsoft, что к 2006 году тактовая частота процессоров достигнет 6 ГГц. Мы приближаемся к концу 2020 года, а флагманские игровые процессоры едва достигают 5 ГГц. Вычислительное оборудование никогда не переставало развиваться; однако, оно перестало прогрессировать тривиально, по крайней мере, с точки зрения программных компаний.
В 1980-х и 1990-х годах, как только программа начинала работать, даже если по состоянию на момент выпуска она была несколько медленной, было очевидно, что уже в следующем году её скорость станет приемлемой, а через год — отличной. Агрессивные компании-разработчики, такие как Microsoft, прекрасно использовали этот аргумент: их инженерам предоставлялось (и до сих пор предоставляется) лучшее вычислительное оборудование, которое только можно купить, и они систематически доводили производительность программного обеспечения до предела допустимого, зная, что аппаратное обеспечение в основном решит проблему с производительностью через год или два. После провала Vista инженеры Microsoft осознали масштабы проблемы и изменили свои методы — Windows 7 стала значительным улучшением. Однако потребовалось десятилетие, чтобы Windows действительно восстановилась в плане производительности. В наши дни ситуация практически обратная: лучшие команды Microsoft уже не делают ставку на будущее аппаратное обеспечение, а сосредотачиваются почти исключительно на достижении немедленной превосходной производительности за счет лучшего программного обеспечения5.
Однако мир корпоративного программного обеспечения оказался намного медленнее в распознании проблемы и продолжал разрабатывать софт в течение 2010-х так, как если бы будущее вычислительное оборудование вот-вот решило все их проблемы, как это происходило не раз в прошлом. К сожалению, для большинства поставщиков корпоративного софта, несмотря на то, что вычислительное оборудование все еще прогрессирует, еще десятилетие назад прогресс прекращался тривиально6, когда поставщик мог просто дождаться улучшения производительности. Программное обеспечение со временем склонно накапливать избыточность (больше функций, больше опций, больше экранов и т.д.). Таким образом, естественная тенденция сложного софта — замедляться со временем, а не улучшаться, если только не прикладываются интенсивные целенаправленные усилия.
К сожалению, с точки зрения продаж, производительность — в основном незначительный вопрос. Демонстрации проводятся с использованием тестовых аккаунтов, которые содержат лишь ничтожно малую долю объема данных, с которым система столкнется в рабочем режиме. Кроме того, экраны, представляющие интерес для топ-менеджмента, получают непропорционально больше полировки по сравнению с теми, что предназначены для рядовых сотрудников. Однако именно эти последние экраны используются тысячи раз в день и поэтому заслуживают наибольшего внимания. Я подозреваю, что API часто демонстрируют ужасную производительность, потому что немногие покупатели проверяют, соответствует ли эта производительность их ожиданиям. Поставщики программного обеспечения знают это и соответственно направляют свои инженерные инвестиции.
Это подводит меня ко второму аспекту проблемы производительности: отсутствию внимания к внутреннему дизайну решения. В настоящее время, чтобы воспользоваться основной массой постоянных улучшений аппаратного обеспечения, требуются стратегические решения в области дизайна программного обеспечения. Однако такое решение — обоюдоострый меч: оно дает возможности, но одновременно и накладывает ограничения. Необходимы сильные лидеры, способные обеспечить приверженность решению как на бизнес-стороне, так и на технической стороне. Нерешительность проще, но, как показывает подавляющее большинство корпоративного софта, производительность (а также UX в целом) сильно страдает.
Одной из проблем современного программного обеспечения (и не только корпоративного) является избыточное количество слоев. Данные копируются, передаются по каналам, объединяются, синхронизируются и т.д. через десятки внутренних слоев программы. В результате большая часть вычислительных ресурсов тратится на «внутреннюю проводку», которая сама по себе не добавляет ценности. С точки зрения дизайна, решение этой проблемы одновременно и просто в концепции, и сложно в реализации: необходимо экономно использовать сторонние компоненты, особенно те, которые добавляют дополнительный слой7. С позиции поставщика софта добавление еще одного слоя — самый быстрый способ добавить больше «крутых функций» в продукт, не говоря уже о раздувании.
В Lokad мы выбрали вариант глубоко интегрированного стека, спроектировав всю нашу платформу вокруг ядра компилятора. С другой стороны, мы теряем возможность легко интегрировать любой случайный проект с открытым исходным кодом в нашу систему. Интеграция по-прежнему возможна, но обычно требует более глубоких изменений в самом компиляторе. С другой стороны, мы достигаем «низкоуровневой» производительности, которая обычно считается невообразимой с точки зрения корпоративного софта. В целом, учитывая, что компоненты с открытым исходным кодом стареют плохо, этот подход оказался особенно эффективным за последнее десятилетие8.
Мультиарендная (совместная) инфраструктура — еще один архитектурный выбор, который радикально влияет на производительность, по крайней мере, с точки зрения соотношения цена/качество. Большинство корпоративного программного обеспечения — в том числе и для цепочки поставок — имеет резко переменные требования к вычислительным ресурсам. Например, на крайнем конце спектра у нас находится прогнозирование на основе числовых методов, которое запускается всего один раз в день (или около того), но должно обрабатывать всю историческую базу данных каждый раз. Наличие статического набора вычислительных ресурсов9, выделенного для одного клиента, является чрезвычайно неэффективным.
Опять же, в Lokad мы выбрали полностью совместную инфраструктуру. Этот подход снижает наши операционные расходы на облако, одновременно обеспечивая производительность, которая была бы экономически нецелесообразной в противном случае (затраты на облако перевешивали бы преимущества цепочки поставок). Чтобы обеспечить бесперебойную координацию всех рабочих нагрузок, мы разработали высокую степень «предсказуемости» при использовании вычислительных ресурсов. DSL от Lokad (предметно-ориентированный язык программирования), названный Envision, был создан для поддержки этой задачи. Именно поэтому в Envision отсутствуют целые классы программных конструкций — например, произвольные циклы: эти конструкции несовместимы с требованиями «высокой предсказуемости», которые предъявляет обработка данных цепочки поставок.
В заключение, не рассчитывайте, что «толстая» система цепочки поставок скоро станет «стройной», если она уже не является таковой. Хотя вычислительное оборудование продолжает развиваться, оно уже достаточно быстрое. Если система медленная, скорее всего, это потому, что она противостоит своему базовому аппаратному обеспечению, а не из-за его недостатка. Проблему можно исправить, но в основном это вопрос дизайна. К сожалению, базовый дизайн программного обеспечения — одна из тех вещей, которые практически невозможно исправить в корпоративном софте после стадии проектирования продукта. Однако восстановление возможно, как показала Microsoft, но не каждая компания (как поставщик, так и клиент) может позволить себе десятилетие на это.
-
Еще в 2012 году я опубликовал ReceiptStream — небольшой проект с открытым исходным кодом, чтобы продемонстрировать, что хранение примерно годовой истории транзакций Walmart на уровне корзин на SD-карте не только возможно, но и осуществимо с помощью нескольких сотен строк кода. ↩︎
-
Мы стараемся выполнять поэтапное извлечение данных, если системы позволяют это делать. Однако первоначальное извлечение данных обычно охватывает период за 3–5 лет, так как наличие исторической глубины действительно помогает при анализе сезонных колебаний. ↩︎
-
Терминалы консоли могут выглядеть устаревшими, но если эти системы существуют на протяжении нескольких десятилетий, значит, у них, вероятно, есть немало компенсирующих достоинств, например, низкая задержка отклика. Нет ничего более раздражающего, чем современный веб-интерфейс с эффектным дизайном, где обновление страницы занимает несколько секунд. ↩︎
-
Я не утверждаю, что терабайты ОЗУ не могут быть полезны для оптимизации цепочки поставок — повторяя вымышленную цитату, ошибочно приписываемую Биллу Гейтсу, что «640K должно хватить для любого». Моя мысль в том, что нерациональное использование вычислительных ресурсов является упущенной возможностью использовать их с большей эффективностью. По состоянию на декабрь 2020 года я не вижу причин, по которым требуется такое количество памяти, учитывая (отсутствие) сложности числовых методов, задействованных в парадигме «вычислений в памяти». ↩︎
-
Улучшения производительности, практически полностью обусловленные софтом, внесенные .NET Core 1, .NET Core 2, .NET Core 3 и .NET 5, являются образцовыми в этом отношении. Некоторые ускорения основаны на инструкциях SIMD (одна инструкция, несколько данных), однако эти инструкции вряд ли можно назвать «аппаратным будущим», поскольку большинство процессоров, продаваемых за последнее десятилетие, уже обладают такими возможностями. ↩︎
-
Выявленные аппаратные уязвимости, такие как Meltdown, отрицательно сказались на производительности существующего вычислительного оборудования. Можно ожидать больше подобных проблем в будущем. ↩︎
-
Слои бывают самых разных форм. Docker, HDFS, Python, NumPy, Pandas, TensorFlow, Postgres, Jupyter … — все они являются важными компонентами, и каждый из них вводит свой собственный программный слой. ↩︎
-
Когда я основал Lokad в 2008 году, я решил создать собственное прогнозирующее ядро. Однако в то время R был на пике популярности. В 2012 году — Hadoop. В 2014 году — Python и SciPy. В 2016 году — Scikit. В 2018 году — TensorFlow. В 2020 году — Julia. ↩︎
-
Критерием для определения того, использует ли якобы SaaS (Software as a Service) взаимную многопользовательскую архитектуру, является проверка возможности регистрации для получения бесплатного аккаунта. Если поставщик не может предоставить бесплатный аккаунт, то почти наверняка он занимается исключительно моделью ASP (Application Service Provider), а не SaaS. ↩︎