[Moscow.pm] Очень медленное нахождение элемента в массиве

zhecka zhecka на gmail.com
Пт Ноя 25 04:41:46 PST 2016


по сути лучше не использовать ip адреса в виде scalar string
переведи адреса в integer и будет много быстрее.
Плюс вместо цикла перебора и поиска можно уйти на Cache::FastMmap и 
работать через ключи. выборка будет быстрее чем поиск по массиву.

On 25.11.2016 15:36, Naim Sh via Moscow-pm wrote:
>
> @ips даже этим относительно медленным способом
>
>
>    while (my $ip = $sql->fetchrow_array)
>     {
>         push @ips,$ip;
>     }
>
> дает максимум десятки ms  задержок  и потом уже код который я отсылал .
>
> On 11/25/2016 04:16 PM, Толян II via Moscow-pm wrote:
>> У тебя сам цикл тормозит, а не grep
>> ==================================================================================
>>     use Time::HiRes qw(time);
>>     use NetAddr::IP;
>>
>> my @ips = (
>>         map("172.16.1.".$_, 1..254 ),
>>         map("172.16.2.".$_, 1..254 ),
>>         map("172.16.3.".$_, 1..254 ),
>>         map("172.16.4.".$_, 1..254 ),
>> );
>>
>>     for my $i ( 0 .. 4 ) {
>>         my $iponly = 995 + $i;
>>         my $s      = time();
>>         my %ips    = map { $_ => 1 } @ips;
>>         my $r1     = ( not exists $ips{$iponly} );
>>         my $time1  = time - $s;
>>
>>         $s = time();
>>         my $r2 = grep $_ eq $iponly, @ips;
>>         my $time2 = time - $s;
>>
>>         $s = time();
>>         my $ipn = NetAddr::IP->new("172.16.1.1/16 
>> <http://172.16.1.1/16>");
>>         while($ipn < $ipn->broadcast){
>>             my $iponly = (split "/", $ipn++)[0];
>>         }
>>
>>         my $time3 = time - $s;
>>
>>         printf( "i=$i\tmap=%4.3fms grep=%4.3fms while=%4.3fms\n", 
>> $time1 * 1000, $time2 * 1000, $time3 * 1000 );
>>     }
>> =================================================================================
>>
>>
>> i=0     map=0.572ms grep=0.136ms while=1726.824ms
>> i=1     map=0.407ms grep=0.052ms while=1752.693ms
>> i=2     map=0.394ms grep=0.048ms while=1701.981ms
>> i=3     map=0.507ms grep=0.063ms while=1786.335ms
>> i=4     map=0.823ms grep=0.053ms while=1704.208ms
>>
>> ==================================================================================
>>
>>
>> А если в @ ips еще overloaded ip, то и 10 секунд легко может быть
>>
>> В твоем куске не видно как они получаются.
>>
>>
>>
>> 25 ноября 2016 г., 15:10 пользователь Naim Sh via Moscow-pm 
>> <moscow-pm на pm.org> написал:
>>
>>     Оки, я просто думаю щас затестить не весь модуль NetAddr::IP а
>>     его lite версию ( хотя как я предполагаю выигрыш будет
>>     маленький)  + щас переустановил точнее пересобрал его xs стало
>>     лучше .
>>
>>     + надо затестить как она будет с broadcast и subnet-zero сетками
>>     пахать .
>>
>>     On 11/25/2016 04:07 PM, zhecka via Moscow-pm wrote:
>>>     ну я бы не сказал.
>>>
>>>     $banned = new Net::Patricia;
>>>     if(!$banned->match_string($banip))
>>>         {
>>>              $banned->add_string($banip);
>>>         }
>>>
>>>     просто заполняешь базу Patricia когда тебе нужно и матчишь что
>>>     есть и чего нет.
>>>
>>>
>>>
>>>     On 25.11.2016 14:54, Naim Sh via Moscow-pm wrote:
>>>>
>>>>     да кроме 2 и 3  его нету .
>>>>
>>>>     Кстати как я понял Net::Patricia не очень мне подходит(удобен)
>>>>     ведь мне надо найти адрес которого нет в массиве
>>>>
>>>>     This module uses a Patricia Trie data structure to quickly
>>>>     perform IP address prefix matching for applications such as IP
>>>>     subnet, network or routing table lookups ?
>>>>
>>>>     On 11/25/2016 03:50 PM, Толян II via Moscow-pm wrote:
>>>>>     У тебя может быть overload в нескольких местах:
>>>>>     1) В массиве @ips
>>>>>     2)  while( $ipn < $ipn->broadcast )              --- вызов
>>>>>     метода + overload
>>>>>     3) my $iponly = (split '/', $ipn++)[0]; #get--- overload в
>>>>>     чистом виде + преобразование в строку.
>>>>>
>>>>>
>>>>>
>>>>>
>>>>>     25 ноября 2016 г., 14:38 пользователь Naim Sh via Moscow-pm
>>>>>     <moscow-pm на pm.org <mailto:moscow-pm на pm.org>> написал:
>>>>>
>>>>>         Оки и какой вариант быстрее того же map будет .
>>>>>         код имеет такой вид ( точнее его кусок который больше
>>>>>         всего времени и ест )
>>>>>
>>>>>         массив @ips имеет стандартные ipv4 адреса типа 10.56.6.2,
>>>>>         10.135.8.23  , 10.135.22.43 и тд и тп .
>>>>>
>>>>>                 my $ipn = NetAddr::IP->new("$first_ip/$netmask");
>>>>>
>>>>>                 while( $ipn < $ipn->broadcast )
>>>>>                 {
>>>>>                     my $iponly = (split '/', $ipn++)[0]; #get
>>>>>
>>>>>                     if ( ! ( grep {$iponly eq $_}  @ips )  )
>>>>>                     {
>>>>>                         return $iponly;
>>>>>                     }
>>>>>
>>>>>                 }
>>>>>
>>>>>         first отдает не то что мне нужно из под этой сети адрес в
>>>>>         данном случае 10.135.x.y а 10.56.x.y хотя да он первый
>>>>>         пустой, но grep выдает то что нужно.
>>>>>
>>>>>         Вроде tie переменных и т.д нету
>>>>>
>>>>>
>>>>>
>>>>>         On 11/25/2016 03:29 PM, Sergey Aleynikov via Moscow-pm wrote:
>>>>>
>>>>>             Добрый день,
>>>>>
>>>>>             map будет быстрее только если поисков по одному и тому
>>>>>             же исходному
>>>>>             массиву @ips будет несколько - т.к. операция
>>>>>             построения хэша дорогая.
>>>>>             Одноразовый поиск - греп быстрее. first возвращает
>>>>>             другое (по смыслу)
>>>>>             значение, чем греп (элемент, а не количество), но
>>>>>             логически для этой
>>>>>             задачи разницы быть не должно.
>>>>>
>>>>>             PS: my %ips; @ips{@ips} = (); быстрее, чем my %ips =
>>>>>             map { $_ => 1 } @ips;
>>>>>
>>>>>             Best regards,
>>>>>             Sergey Aleynikov
>>>>>
>>>>>
>>>>>             25 ноября 2016 г., 14:00 пользователь Naim Sh via
>>>>>             Moscow-pm
>>>>>             <moscow-pm на pm.org <mailto:moscow-pm на pm.org>> написал:
>>>>>
>>>>>                 Коллеги, столкнулся с тем что код такого вида ,
>>>>>                 используемый для поиска
>>>>>                 свободных ip v4 адресов на размерах 500-1000
>>>>>                 элементов отрабатывается под 5
>>>>>                 секунд версия с map :
>>>>>
>>>>>                 my %ips = map { $_ => 1 } @ips;
>>>>>                 if (not exists($ips{$iponly} ))
>>>>>                 {
>>>>>                          return $iponly;
>>>>>                 }
>>>>>
>>>>>
>>>>>                   и с grep(sic!) ~2 секунду :
>>>>>
>>>>>                 if ( ! ( grep {$iponly eq $_ } @ips ) )
>>>>>                 # spent 27.4ms making 814 calls to
>>>>>                 NetAddr::IP::Lite::broadcast, avg
>>>>>                 34µs/call
>>>>>                 # spent 9.56ms making 814 calls to
>>>>>                 NetAddr::IP::Lite::__ANON__[NetAddr/IP/Lite.pm:268],
>>>>>                 avg 12µs/call
>>>>>                 {
>>>>>                      return $iponly;
>>>>>                 }
>>>>>
>>>>>                 Еще трабла в том что легендарный List::Util отдает
>>>>>                 быстро но почему не тот
>>>>>                 же результат( пробовал first , none ) что и grep?
>>>>>
>>>>>                 коллеги это нормально на более-менее среднем
>>>>>                 сервачке ?
>>>>>
>>>>>
>>>>>                 --
>>>>>                 Moscow.pm mailing list
>>>>>                 moscow-pm на pm.org <mailto:moscow-pm на pm.org> |
>>>>>                 http://moscow.pm.org
>>>>>

----------- следущая часть -----------
Вложение в формате HTML было извлечено…
URL: <http://mail.pm.org/pipermail/moscow-pm/attachments/20161125/1a274516/attachment-0001.html>


Подробная информация о списке рассылки Moscow-pm