Коли кеш росте не в той бік
У теці кешу цієї служби лежать чотири маленькі файли. Найбільший — 35 байтів. Разом вони містять три номери лічильників, і їх читають при кожному зверненні до лічильника.
Вони є, щоб шлях підрахунку не ставив базі чотирьох питань, на які майже завжди відповідає «ні». Чи виключає цей лічильник власні відвідини власника? Чи рахує вихідні кліки? Чи стежить за шляхами сайтом? Чи перезавантажує сам себе? Більш ніж для 99 % лічильників кожна відповідь — ні, і файл із жменькою номерів, де відповідь «так», обходиться дешевше, ніж чотири запити за індексом.
Обходиться дешевше. І це та дешевизна, що перевертається.
Що вимірювали
Те саме питання — «чи є цей лічильник у списку?» — поставлене двома способами, за шести довжин списку. Шлях через файл: прочитати, розібрати JSON, пошукати номер. Шлях через базу: один підготовлений запит до стовпця з індексом. По дві тисячі повторів, п'ять кіл, узята медіана.
За нинішнього розміру файл виграє увосьмеро: 0,0202 мілісекунди проти 0,1630. За тисячі номерів вони врівень. За десяти тисяч файл коштує вдванадцятеро дорожче, а за ста тисяч — у 135 разів, бо на той час це 578 кілобайтів, які треба прочитати й розібрати при кожному зверненні.
Лінія бази не рухається. 0,16 мілісекунди за двох рядків і 0,16 за ста тисяч: для цього індекс і потрібен, і легко забути, скільки роботи сховано за такою нудною лінією.
Незручна частина
Перетин — між 100 і 1 000 номерами. У цієї служби 2 218 лічильників, які мали звернення за останні тридцять днів.
Отже, якби виключення виявилося успіхом — якби кожен, хто має лічильник, увімкнув «не рахувати мої власні відвідини» — файл містив би 2 218 номерів, важив 11 кілобайтів і коштував 0,43 мілісекунди на звернення замість 0,02. За вчорашніх 18 423 звернень це вісім секунд роботи на день заради того, щоб уникнути запиту, який зайняв би три.
Оптимізація найшвидша тоді, коли можливістю найменше користуються. Вона не псується поступово під навантаженням, як повільний запит. Вона псується мірою поширення, а це єдина вісь, за якою ніхто не стежить, бо зростання поширення нібито добра новина.
Чому це все-таки лишається
Бо сьогодні це правильно, а «сьогодні правильно» має право бути причиною, поки хтось записав, коли це перестане бути правдою.
Три номери у трьох файлах. Увосьмеро дешевше за альтернативу, на машині, де шлях підрахунку — єдине, що мусить бути швидким. Замінити це зараз запитом, який він перемагає, означало б дістати гіршу систему, виправдану припущенням.
Бракує розтяжки, а не переробки. Файл і так пишеться з бази — кодом, що змінює налаштування. Це і є природне місце, щоб помітити, що список перевалив за кілька сотень записів, і сказати про це. Кеш із записаною межею — це рішення. Кеш без межі — це парі, на яке ніхто не погоджувався.
Загальна форма
Це не довід проти кешу у файлі. Це довід за те, щоб знати, у який бік росте ваш кеш.
Більшість кешів під навантаженням стають кращими: більше запитів, більше влучань, краща частка. Цей — іншого роду. Його вартість на запит залежить від того, скільки він у собі тримає, а тримає він те, що росте разом зі справою, яку служба й хоче заохочувати. Кожне читання платить за кожен запис, зокрема за ті 2 215, що не мають стосунку до відвідувача, якого рахують саме зараз.
Питання до будь-якої довідкової таблиці в пам'яті чи у файлі не «наскільки вона швидка», а «від чого вона росте і що буде, коли це піде добре». Якщо відповідь «стане повільнішою», обмеження розміру належить кодові — поруч із тим, що пише файл, того дня, коли його будують.