по сути лучше не использовать 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
<[email protected]> написал:
Оки, я просто думаю щас затестить не весь модуль 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
<[email protected] <mailto:[email protected]>> написал:
Оки и какой вариант быстрее того же 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
<[email protected] <mailto:[email protected]>> написал:
Коллеги, столкнулся с тем что код такого вида ,
используемый для поиска
свободных 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
[email protected] <mailto:[email protected]> |
http://moscow.pm.org
--
Moscow.pm mailing list
[email protected] | http://moscow.pm.org