MidТеория5 min

Зачем оценивать

Back-of-envelope расчёты в system design: почему нужен правильный порядок величины, power of 2 vs power of 10, когда оценки не нужны

Суть back-of-envelope

Back-of-envelope (BOTE) -- это быстрая прикидка "на салфетке": вы не собираетесь получить точный ответ, вы ищете правильный порядок величины. Вопрос не "1243 QPS или 1587 QPS?", а "сотни, тысячи или миллионы?". Разница между 10^3 и 10^6 меняет архитектуру: single node vs шардированный кластер, Postgres vs Cassandra, in-memory cache vs CDN.

Два случая, где BOTE критичен

  1. System design interview. Интервьюер хочет увидеть, что вы не боитесь цифр и умеете привязать решение к нагрузке. "Нужен Redis" без обоснования -- слабый ответ. "При 50k QPS чтения и working set 20 GB Redis оправдан" -- сильный.
  2. Реальное проектирование. Решение "взять Kafka" стоит команде месяцы работы. Если peak нагрузка 100 msg/sec -- Kafka избыточен, хватит RabbitMQ или даже Postgres. Если 1M msg/sec -- Kafka минимум, но нужно планировать партиционирование.

Когда оценки НЕ нужны

  • Прототип, MVP, внутренний инструмент на 10 пользователей -- любая разумная технология справится
  • Задача чисто алгоритмическая (правильность > производительности)
  • Уже есть production-метрики реальной системы -- используйте их, а не прикидки

Power of 2 vs Power of 10

Инженеры путают KB/KiB, MB/MiB. На BOTE это не критично (погрешность 2.4% на KB, 7.4% на GB), но важно понимать обе системы.

Префикс SI (10^n) Значение Префикс IEC (2^n) Значение Разница
KB (kilobyte) 10^3 = 1 000 KiB (kibibyte) 2^10 = 1 024 +2.4%
MB (megabyte) 10^6 = 1 000 000 MiB (mebibyte) 2^20 = 1 048 576 +4.9%
GB (gigabyte) 10^9 GiB (gibibyte) 2^30 ≈ 1.07×10^9 +7.4%
TB (terabyte) 10^12 TiB (tebibyte) 2^40 ≈ 1.10×10^12 +10.0%
PB (petabyte) 10^15 PiB (pebibyte) 2^50 ≈ 1.13×10^15 +12.6%

Практическое правило BOTE. Используйте power of 2 для памяти/storage и power of 10 для QPS/bandwidth. На уровне PB разница уже 12% -- округляйте в "плохую" сторону (больше storage, выше latency).

Таблица мощностей двойки

Это маст-хэв для BOTE. Запомните хотя бы до 2^40.

Степень Значение Человеческое название
2^10 1 024 ~1 тысяча (Ki)
2^16 65 536 ~65 тысяч (max uint16, порт)
2^20 1 048 576 ~1 миллион (Mi)
2^24 16 777 216 ~16 миллионов (RGB cube)
2^30 1 073 741 824 ~1 миллиард (Gi)
2^32 4 294 967 296 ~4.3 миллиарда (IPv4, max uint32)
2^40 1.1×10^12 ~1 триллион (Ti)
2^50 1.13×10^15 ~1 квадриллион (Pi)
2^64 1.84×10^19 ~18 квинтиллионов (max uint64)

Typical scales систем

Держите в голове порядки величин, с которыми работают реальные системы.

Масштаб Примеры QPS Storage
Small Внутренний tool, startup MVP 1-100 < 10 GB
Medium B2B SaaS, региональный сервис 100-10k 10 GB - 1 TB
Large Крупный e-commerce, национальный сервис 10k-100k 1-100 TB
Huge Топ-100 сайт мира 100k-1M 100 TB - 10 PB
Hyperscale Google, Meta, Amazon > 1M > 10 PB

Округление и точность

Правила BOTE:

  1. Округляйте агрессивно. 86400 секунд в сутках ≈ 100k (или 10^5). 365 дней ≈ 400 (10^2.6). Погрешность 15-20% не важна на уровне "нужен или нет шардинг".
  2. Округляйте в "плохую" сторону. Если считаете нагрузку -- вверх. Если считаете бюджет -- вниз. Это даёт запас.
  3. Считайте peak, не average. Peak/average обычно 2-4x для web, 10x для retail в чёрную пятницу. Проектируйте под peak.
  4. Запас x2-x3. Нагрузка растёт, хостинг падает, метрики ошибаются. Всегда добавляйте запас.

Полезные приближения

  • 1 день ≈ 10^5 секунд (точно 86 400)
  • 1 месяц ≈ 30 дней ≈ 2.6×10^6 секунд
  • 1 год ≈ 400 дней ≈ 3×10^7 секунд
  • 1 Gbps ≈ 125 MB/s (точно 125 MB/s для power of 10)
  • ASCII-символ = 1 byte, UTF-8 кириллица = ~2 bytes
  • UUID в hex = 36 bytes, в bin = 16 bytes

Хелпер: вычисление степеней

Простые утилиты для человекочитаемых размеров.

<?php

declare(strict_types=1);

/**
 * Binary size helper: converts bytes to human-readable form and back.
 * Uses power-of-2 (IEC) units: KiB, MiB, GiB, TiB, PiB.
 */
final class BinarySize
{
    private const UNITS = ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB'];

    /**
     * Format bytes into the largest unit where value >= 1.
     * Example: format(1536) => "1.5 KiB"
     */
    public static function format(int|float $bytes, int $precision = 2): string
    {
        if ($bytes < 1) {
            return '0 B';
        }

        $exp = (int) floor(log($bytes, 1024));
        $exp = min($exp, count(self::UNITS) - 1);
        $value = $bytes / (1024 ** $exp);

        return sprintf("%.{$precision}f %s", $value, self::UNITS[$exp]);
    }

    /**
     * Parse "2.5 GiB" back into bytes.
     */
    public static function parse(string $input): int
    {
        if (!preg_match('/^\s*(\d+(?:\.\d+)?)\s*([KMGTPE]?i?B)\s*$/i', $input, $m)) {
            throw new \InvalidArgumentException("Invalid size format: {$input}");
        }

        $value = (float) $m[1];
        $unit = strtoupper($m[2]);
        $idx = array_search($unit, array_map('strtoupper', self::UNITS), true);

        if ($idx === false) {
            throw new \InvalidArgumentException("Unknown unit: {$unit}");
        }

        return (int) round($value * (1024 ** $idx));
    }

    /**
     * Raw power of 2: pow2(30) => 1073741824.
     */
    public static function pow2(int $exp): int
    {
        return 1 << $exp;
    }
}

// Usage:
// BinarySize::format(5 * 1024 ** 3) => "5.00 GiB"
// BinarySize::parse("500 MiB") => 524288000
## Чек-лист перед оценкой

Перед расчётом задайте 5 вопросов:

  1. DAU / MAU? Сколько реальных пользователей в день/месяц?
  2. Actions per user? Сколько действий на пользователя в день?
  3. Read/write ratio? Соцсеть -- 100:1 read. Аналитика -- 1:100.
  4. Object size? Tweet -- 280 байт. Photo -- 2 MB. Video -- 50 MB.
  5. Retention? Хранить месяц, год, вечно?

Ответив на них, получите QPS, storage, bandwidth за 2-3 минуты.

Выводы

  • BOTE -- правильный порядок величины, не точная цифра
  • Power of 2 для памяти/storage, power of 10 для QPS/bandwidth -- погрешность до 12.6% на PB
  • Запомните мощности двойки до 2^40: 10^3, 10^6, 10^9, 10^12
  • Считайте peak, округляйте вверх, добавляйте x2-x3 запас
  • Без оценок архитектурное решение -- гадание; с оценками -- инженерия