Войти Регистрация
Фронтенд

65. Кэш превью фото Wildberries с лимитом в байтах

Сложная

Мобильная веб-версия Wildberries держит в памяти превью фото товаров, чтобы при возврате в каталог не качать их заново. Превью весят от 8 до 120 КБ, поэтому лимит «200 записей» не работает: 200 больших превью — 24 МБ, и вкладку на слабом Android выгружает.

Напишите класс ByteLRU. Конструктор new ByteLRU({ maxBytes, sizeOf }), где sizeOf(value) возвращает размер в байтах. get(key) возвращает значение или undefined и делает запись самой свежей. peek(key) — то же без освежения. delete(key) → true, если запись была.

set(key, value) кладёт или заменяет запись, делает её самой свежей и вытесняет самые старые, пока сумма размеров больше maxBytes. Только что положенную запись не вытесняем. Если sizeOf(value) > maxBytes, запись не кладётся, старое значение по этому ключу удаляется, set возвращает false; иначе true.

bytes — текущая сумма размеров, keys() — массив ключей от самого старого к самому свежему.

В работе: Лимит 8 МБ на превью: одно фото на 120 КБ вытесняет пять маленьких по 25 КБ, а не одно.

Пример 1: большое превью вытесняет несколько маленьких

Аргументы теста
100, [["set", "sku1", "aaaaaaaaaaaaaaaaaaaaaaaaa"], ["set", "sku2", "bbbbbbbbbbbbbbbbbbbbbbbbb"], ["set", "sku3", "ccccccccccccccccccccccccc"], ["set", "sku4", "ddddddddddddddddddddddddd"], ["set", "sku5", "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"], ["state"]]
Ожидается
[true, true, true, true, true, [85, ["sku4", "sku5"]], ["вызовов sizeOf", 5]]

Пример 2: get освежает, peek нет

Аргументы теста
60, [["set", "a", "xxxxxxxxxxxxxxxxxxxx"], ["set", "b", "yyyyyyyyyyyyyyyyyyyy"], ["set", "c", "zzzzzzzzzzzzzzzzzzzz"], ["get", "a"], ["peek", "b"], ["set", "d", "wwwwwwwwwwwwwwwwwwww"], ["state"]]
Ожидается
[true, true, true, "xxxxxxxxxxxxxxxxxxxx", "yyyyyyyyyyyyyyyyyyyy", true, [60, ["c", "a", "d"]], ["вызовов sizeOf", 4]]
Как проверяем Объявите ByteLRU — тест вызывает её сам. Таймеры и Date в тестах ненастоящие: время идёт по команде теста, поэтому setTimeout на 5 секунд проверяется мгновенно. Тестов 8: 2 открыты выше, остальные приходят после старта подхода. Лимит — 2 с на тест.
class ByteLRU { constructor({ maxBytes, sizeOf }); get(key); peek(key); set(key, value) → boolean; delete(key) → boolean; get bytes(); keys() }
LRUMapвытеснениеучёт памяти

Источник: на задачах Wildberries: превью фото в карточках. Условие пересказано своими словами.