В третий раз о том, что лучше, переписать код или улучшить железо
На тему заголовка недавно написано два поста Что дешевле: новое железо или труд разработчиков? и Почему нет простых решений о том, что лучше — купить серверов или оптимизировать код.
Почитал и решил, что не всё досказано даже в этих двух статьях.
Давайте посмотрим на конкретные варианты, чтобы понять абсурдность абстрактных рассуждений на эту тему.
1. Мы знаем, так как уже неоднократно находили ошибки, что наш код можно оптимизировать и, вообще, он недостаточно хорош
Очевидно, что многие программные системы развиваются второпях. Иногда они просто бурно развиваются несколько лет.
После этого всегда требуется анализ кода, рефакторинг и т.п.
Например. У нас в фирме слабо использовалась многопоточность, т.к. сервер IIS сам по себе обрабатывал запросы параллельно.
Однако в некоторый момент оказалось, что использование многопоточности необходимо, так как запрос стал обрабатываться без этого по 30-40 секунд.
Я начал использовать многопоточность и сразу же нашёл несколько ошибок в уже существующем пару лет коде с синхронизацией.
Я был первым, у кого вообще по этой причине стал падать код.
Возникает вопрос, если есть время, что лучше, выбрать рефакторинг кода с улучшениями или купить оборудование?
Ответ прост: код и так нуждается в рефакторинге, поэтому
1. Необходимо провести рефакторинг и обратить внимание на оптимизацию, параллельность, кеширование и соединение нескольких последовательных сетевых запросов в один.
2. Если рефакторинг не даёт результата до требуемого уровня, необходимо покупать оборудования.
3. При рефакторинге выделить, прежде всего, именно те куски кода, что создают больше всего проблем, но которые не содержат принципиальных трудностей к исправлению
Здесь ситуация понятна: без рефакторинга всё равно не жить. Но эта ситуация очень часта: если уж нагрузка зашкаливает, то, скорее всего, и кода уже наворочено поверх фундамента выше крыши, так что всё рушится.
Поэтому рефакторинг будет в любом случае. Мы не будем переписывать всю систему заново, мы просто доработаем танк до трактора.
Но вот специально зацикливаться на оптимизации больше, чем следует, мы не будем. Мы ведь профессионалы, а не студенты, работающие по книжкам Макконнелла?
2. Мы провели нагрузочное тестирование и получили вывод о плохой масштабируемости системы
Подключив 11 процессоров мы получили производительность в 11 условных единиц. Подключив 22 процессора мы получили производительность в 15,5 условных единиц. Подключив 64 процессора мы получили производительность в 26,4 у.е.
Вывод тестировщиков: система не масштабируется должным образом. В результате покупки оборудования мы всегда будем тратить очень много денег.
На исправление требуется разнести одну базу данных на два разных сервера, выделить сервер транзакций, написать сервер транзакций и новое звено многозвенной архитектуры.
1. Т.к. на всё это потребуется год, а за это время наш бизнес вырастет на 40%, нам требуется довольно быстро купить вдвое более мощный сервер. То есть выделяем деньги на оборудование. Кроме этого, нам потребуется второй сервер и сервер транзакций и публичного звена, проксирующего распределённую систему на один сетевой адрес.
Таким образом, через год мы купим ещё один сервер вдвое мощнее, чем сейчас.
Через 1,5 года мы сможем обслуживать в 2,8 раза больше клиентов, чем сейчас за счёт улучшения производительности в 4 раза и улучшения архитектуры. Через 3 года мы купим ещё один сервер и сможем обслуживать в 7,8 раз больше клиентов, чем сейчас.
То есть опять деньги на оборудование.
2. Переписывание системы также потребует денег и времени.
В этой ситуации, так же как и в первом пункте, нет никакого компромиса между тем или этим. Если в первом пункте обязательно нужен рефакторинг, то здесь нужно и кодирование, и сервера.
3. Наш сайт подвергся DDOS-атаке и упал
Наш сайт подвергся атаке. Вместе с ним упал и сервер продукции, так как канал связи с ним был перегружен.
Наш сайт нам не так важен, поэтому оставляем всё как есть.
Наш сервер продукции нам очень важен. Мы не можем оставить всё как есть. Однако, наш сервер продукции не предназначен для распараллеливания.
Что же делать?
Всё довольно просто.
1. Вынести сервер продукции нафиг за канал связи нашего сайта. Наш сервер продукции известен лишь только нашим клиентам и канал связи могут загрузить только знающие его люди.
2. Канал связи на сервер продукции сделать более быстрым.
3. Сделать проксирующие серверы, которые будут пускать на основной сервер только авторизованных пользователей. Либо, поставить аппаратные межсетевые экраны с авторизацией с организацией доступа к серверу с нескольких точек (для улучшения устойчивости при загрузке одного канала связи). Таким образом мы лишим возможности атаковать нераспараллеливаемую бизнес-логику, а проксирующих серверов мы можем поставить сколько душа пожелает.
Таким образом, решение находится скорее в рамках покупки нового оборудования (межсетевых экранов, каналов связи), чем к переписыванию ПО (максимум — написать проксирующий сервер).
Наша система расчётов хороша и масштабируема
Допустим, мы занимаемся компьютерным моделированием.
Наши сервера строят и решают математические модели. Увеличив количество серверов в 2 раза увеличим производительность на столько же.
Мы писали систему на основе уже существующей и довольно хорошей системы. Мы можем оптимизировать её ещё и ещё, однако это дорого.
Кроме этого, новый сервер мы можем купить по потребности, в то время как оптимизацию кода мы должны делать существенно ранее, чем в этом возникнет реальная потребность.
Таким образом, либо мы рискуем деньгами, выделяя их на оптимизацию из предположения, что проект пойдёт в гору, либо покупаем второй сервер, когда первый перестал справляться с работой, что является менее рискованной операцией. В любом случае, от покупки двух серверов мы не застрахованы, так как бинес, возможно, будет расти ещё и ещё.
Таким образом, решение кроется в покупке нового оборудования.
5. Наша система расчётов хороша, но не масштабируема
Мы решаем на нашей системе сложную и объёмную нелинейную задачу. Математический алгоритм задачи не позволяет её распараллелить даже на два ядра. Система моделирования используется в системе управления сложной херофиговиной.
Решение:
1. Глубокая оптимизация кода, структур данных, использования кешей раличных уровней и мест, где алгоритмы позволяют параллелизм.
2. Сложная и рискованная научная работа на изучение возможностей параллелизации решаемых математических задач.
3. Покупка векторно-конвейерной системы, способной улучшить расчёты (если способна)
4. Покупка системы с более быстрой памятью, но дальше уже не так много куда.
5. Разработка элекронной системы, на базе которой при существующем уровне электроники можно ускорить работу кода засчёт оптимизаций передачи и обработки данных.
Допустим, что каждая работа даст на улучшение на 15%. Выполнив все работы, мы получим улучшение на 75%.
Таким образом, требуется сложная научно-техническая работа для решения данной задачи.
Допустим, нам мало 75%.
Ещё вариант: использование системы остаточных классов для распараллеливания операций сложения и умножения. Если у нас нет операций деления и более сложных операций, не сводимых к операциям сложения и умножения, то мы можем получить повышение производительности, скажем, в 5 раз.
Требуется переработка некоторых вычислительных алгоритмов, перепрограммирование и своя электроника. Но делать нечего: либо так, либо никак.
О чём всё это?
Все эти примеры должны лишь проиллюстрировать то, что решение одной и той же задачи на практике зависит, прежде всего, не от личных предпочтений, а от возможностей и состояния проекта и задач, положенных в его основу.
Автор: fdsc