Pull to refresh

Ограничение количества выполнений метода в секунду

Reading time 2 min
Views 11K
Задача: разработать возможность запускать на выполнение заданное количество операций в секунду.

Требования:

  • Решение должно отрабатывать как можно быстрее (иначе в нем теряется смысл)
  • Решение должно быть потокобезопасным

В результате у меня получилась функция (естественно в составе отдельного класса), которая возвращает true либо false (разрешение для выполнения).

Общий принцип таков. Есть коллекция отпечатков DateTime времени (в комментария подсказали, что разумнее взять Stopwatch). При запросе разрешения проверяется, не превышает ли количество запросов за последнюю секунду максимальное указанное значение. Если превышает, возвращается ложь, иначе в коллекцию добавляется слепок текущего времени и возвращается истина.

Изначально я делал все на основе листов (List<>), но листы имеют динамический набор данных, а значит они расширяются по надобности и при добавлении новых элементов. А надо еще и удалять. Поэтому я решил использовать коллекцию заданного размера. Поэтому от листа решил отказаться в пользу массива. В результате у меня получился функционал круговой коллекции, основанной на массиве, поэтому в итоге я сделал круговую коллекцию.

Получился пул из отпечатков даты заданного размера на основе круговой коллекции. Класс пула содержит текущий элемент, в котором есть отпечаток даты и ссылка на следующий элемент. Изначально все даты имеют значение по умолчанию.

При запросе разрешения берется следующий от текущего элемент, и к его дате прибавляется 1 секунда. Если дата получается больше текущей даты, значит в пуле нет места и запрос возвращает ложь. Иначе в качестве текущего элемента устанавливается следующий, в новом текущем элементе устанавливается слепок даты и возвращается истина.

Теперь о потоках. Я не придумал ничего лучше, как поставить lock на функцию разрешения.

Вот и все.

Для тестирования я создал метод, который выполняет заданное количество запросов с заданным количеством потоков. Запустил его со следующими параметрами. Количество операций в секунду — 6, количество потоков — 4, количество запросов — 50.

Получились вот такие результаты:



Ссылка на гитхаб

По скрину видно, что код отработал верно.
Tags:
Hubs:
If this publication inspired you and you want to support the author, do not hesitate to click on the button
+6
Comments 72
Comments Comments 72

Articles