Как удалить Perl-хэш или элементы массива в зависимости от их возраста? - PullRequest
2 голосов
/ 18 ноября 2009

Как удалить элементы массива, которые меня не интересуют? Если бы я оставил их - моя память была бы переполнена ненужными предметами.

Мне нужно реализовать в Perl одну задачу. Один файл постоянно заполняется сообщениями, содержащими:

 "IP - URL"

Мне нужно постоянно читать этот файл и измерять, было ли, скажем, пять, одинаковых IP - URL пар в, скажем, пятисекундном интервале.

Если я читаю файл с последней позиции каждые пять секунд и подсчитываю дубликаты, я могу столкнуться с ситуацией, когда в течение пяти секунд было восемь одинаковых пар линий, но во время первого чтения их было четыре, а еще четыре были во время второго чтения через пять секунд. Таким образом, мне нужно проверить интервал между последними пятью повторными строками.

Что я могу:

$pairs[$ip_url_line] = ['time-stamp',....,'time-stamp-N']

Затем получите последние пять элементов массива для этого хеш-ключа и вычислите сдвиг времени. Если оно превышает пять секунд - сделайте что-нибудь.

Конечно, я могу запустить все элементы хеша и все элементы массива в цикле и проверить, не старше ли он 5 секунд, но это слишком дорого.

Ответы [ 3 ]

5 голосов
/ 18 ноября 2009
  1. Сохраняйте временные метки для каждого IP-адреса по порядку. Вы, вероятно, собирались сделать это в любом случае.
  2. Всякий раз, когда вы получаете строку журнала и добавляете новую запись, удалите все устаревшие записи прямо перед тем, как проверять, сколько существует записей. Вы можете сделать это легко с grep.
  3. Периодически (раз в минуту?) Удаляйте любые IP-адреса из хеша, которые имеют последнюю (новейшую) временную метку более 5 минут назад, поскольку это означает, что все записи старше 5 минут и этот адрес давно не видели.

Это просто, это легко доказать, что правильно, оно старается не делать слишком много работы за один раз, и это удерживает ваши таблицы от необоснованно больших размеров. С шагом в 1 минуту для шага 3 ни одна запись не может жить более 11 минут. (Если первая запись для 1.2.3.4 была добавлена ​​в 00:00:00, последняя запись может быть добавлена ​​без смещения, первая будет 00:04:59. Последняя развертка шага 3 может выполняться без удаления тогда весь массив будет 00:09:58; при условии, что в худшем случае следующая развертка будет в 00:10:58.) Если вы можете хранить в памяти 11 минут данных, вы просто великолепны.

4 голосов
/ 18 ноября 2009
#!/usr/bin/perl

use strict; use warnings;

my @ts;

for (1 .. 10) {
    push @ts, time;
    sleep rand 3;
}

my $now = time;
@ts = grep { $now - $_ <= 5 } @ts;

print $_, "\n" for @ts;
1 голос
/ 18 ноября 2009

Звучит так, как будто вы хотите использовать какой-то недавно использованный (LRU) кеш. Хотя я не часто рекомендую это, я думаю, что это работа для связанного хэша или массива. Вы STORE новые элементы и, как вы делаете, вы очищаете старые элементы. Это снимает сложность с верхних элементов и скрывает ее за обычным доступом к массиву или хешу. Посмотрите на Tie :: Cache для примера.

В качестве альтернативы, вы можете сохранить некоторый тип FIFO, в котором добавлять новые элементы с одного конца массива, а затем проверять на другом конце элементы для удаления.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...