← Index
NYTProf Performance Profile   « line view »
For /usr/local/bin/sa-learn
  Run on Sun Nov 5 02:36:06 2017
Reported on Sun Nov 5 02:56:18 2017

Filename/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/NetSet.pm
StatementsExecuted 264 statements in 6.71ms
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
1115.04ms23.0msMail::SpamAssassin::NetSet::::BEGIN@35Mail::SpamAssassin::NetSet::BEGIN@35
4211.01ms8.02msMail::SpamAssassin::NetSet::::add_cidrMail::SpamAssassin::NetSet::add_cidr
211296µs2.15msMail::SpamAssassin::NetSet::::_convert_ipv4_cidr_to_ipv6Mail::SpamAssassin::NetSet::_convert_ipv4_cidr_to_ipv6
311152µs282µsMail::SpamAssassin::NetSet::::newMail::SpamAssassin::NetSet::new
411125µs261µsMail::SpamAssassin::NetSet::::_nets_contains_networkMail::SpamAssassin::NetSet::_nets_contains_network
411125µs1.80msMail::SpamAssassin::NetSet::::is_net_declaredMail::SpamAssassin::NetSet::is_net_declared
187197µs383µsMail::SpamAssassin::NetSet::::CORE:matchMail::SpamAssassin::NetSet::CORE:match (opcode)
164177µs77µsMail::SpamAssassin::NetSet::::CORE:substMail::SpamAssassin::NetSet::CORE:subst (opcode)
11146µs70µsMail::SpamAssassin::NetSet::::BEGIN@21Mail::SpamAssassin::NetSet::BEGIN@21
11144µs535µsMail::SpamAssassin::NetSet::::BEGIN@26Mail::SpamAssassin::NetSet::BEGIN@26
11132µs271µsMail::SpamAssassin::NetSet::::BEGIN@31Mail::SpamAssassin::NetSet::BEGIN@31
11131µs65µsMail::SpamAssassin::NetSet::::BEGIN@22Mail::SpamAssassin::NetSet::BEGIN@22
11127µs220µsMail::SpamAssassin::NetSet::::BEGIN@29Mail::SpamAssassin::NetSet::BEGIN@29
11126µs88µsMail::SpamAssassin::NetSet::::BEGIN@24Mail::SpamAssassin::NetSet::BEGIN@24
11125µs32µsMail::SpamAssassin::NetSet::::BEGIN@23Mail::SpamAssassin::NetSet::BEGIN@23
11122µs898µsMail::SpamAssassin::NetSet::::BEGIN@25Mail::SpamAssassin::NetSet::BEGIN@25
11120µs96µsMail::SpamAssassin::NetSet::::BEGIN@28Mail::SpamAssassin::NetSet::BEGIN@28
0000s0sMail::SpamAssassin::NetSet::::DESTROYMail::SpamAssassin::NetSet::DESTROY
0000s0sMail::SpamAssassin::NetSet::::__ANON__[:332]Mail::SpamAssassin::NetSet::__ANON__[:332]
0000s0sMail::SpamAssassin::NetSet::::cloneMail::SpamAssassin::NetSet::clone
0000s0sMail::SpamAssassin::NetSet::::contains_ipMail::SpamAssassin::NetSet::contains_ip
0000s0sMail::SpamAssassin::NetSet::::contains_netMail::SpamAssassin::NetSet::contains_net
0000s0sMail::SpamAssassin::NetSet::::ditch_cacheMail::SpamAssassin::NetSet::ditch_cache
0000s0sMail::SpamAssassin::NetSet::::get_num_netsMail::SpamAssassin::NetSet::get_num_nets
Call graph for these subroutines as a Graphviz dot language file.
Line State
ments
Time
on line
Calls Time
in subs
Code
1# Mail::SpamAssassin::NetSet - object to manipulate CIDR net IP addrs
2# <@LICENSE>
3# Licensed to the Apache Software Foundation (ASF) under one or more
4# contributor license agreements. See the NOTICE file distributed with
5# this work for additional information regarding copyright ownership.
6# The ASF licenses this file to you under the Apache License, Version 2.0
7# (the "License"); you may not use this file except in compliance with
8# the License. You may obtain a copy of the License at:
9#
10# http://www.apache.org/licenses/LICENSE-2.0
11#
12# Unless required by applicable law or agreed to in writing, software
13# distributed under the License is distributed on an "AS IS" BASIS,
14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15# See the License for the specific language governing permissions and
16# limitations under the License.
17# </@LICENSE>
18
19package Mail::SpamAssassin::NetSet;
20
21265µs295µs
# spent 70µs (46+25) within Mail::SpamAssassin::NetSet::BEGIN@21 which was called: # once (46µs+25µs) by Mail::SpamAssassin::Conf::BEGIN@86 at line 21
use strict;
# spent 70µs making 1 call to Mail::SpamAssassin::NetSet::BEGIN@21 # spent 25µs making 1 call to strict::import
22286µs298µs
# spent 65µs (31+33) within Mail::SpamAssassin::NetSet::BEGIN@22 which was called: # once (31µs+33µs) by Mail::SpamAssassin::Conf::BEGIN@86 at line 22
use warnings;
# spent 65µs making 1 call to Mail::SpamAssassin::NetSet::BEGIN@22 # spent 33µs making 1 call to warnings::import
23278µs238µs
# spent 32µs (25+7) within Mail::SpamAssassin::NetSet::BEGIN@23 which was called: # once (25µs+7µs) by Mail::SpamAssassin::Conf::BEGIN@86 at line 23
use bytes;
# spent 32µs making 1 call to Mail::SpamAssassin::NetSet::BEGIN@23 # spent 7µs making 1 call to bytes::import
24267µs2151µs
# spent 88µs (26+62) within Mail::SpamAssassin::NetSet::BEGIN@24 which was called: # once (26µs+62µs) by Mail::SpamAssassin::Conf::BEGIN@86 at line 24
use re 'taint';
# spent 88µs making 1 call to Mail::SpamAssassin::NetSet::BEGIN@24 # spent 62µs making 1 call to re::import
25270µs21.77ms
# spent 898µs (22+876) within Mail::SpamAssassin::NetSet::BEGIN@25 which was called: # once (22µs+876µs) by Mail::SpamAssassin::Conf::BEGIN@86 at line 25
use Time::HiRes qw(time);
# spent 898µs making 1 call to Mail::SpamAssassin::NetSet::BEGIN@25 # spent 876µs making 1 call to Time::HiRes::import
263112µs31.03ms
# spent 535µs (44+491) within Mail::SpamAssassin::NetSet::BEGIN@26 which was called: # once (44µs+491µs) by Mail::SpamAssassin::Conf::BEGIN@86 at line 26
use NetAddr::IP 4.000;
# spent 535µs making 1 call to Mail::SpamAssassin::NetSet::BEGIN@26 # spent 472µs making 1 call to NetAddr::IP::import # spent 19µs making 1 call to UNIVERSAL::VERSION
27
28256µs2173µs
# spent 96µs (20+77) within Mail::SpamAssassin::NetSet::BEGIN@28 which was called: # once (20µs+77µs) by Mail::SpamAssassin::Conf::BEGIN@86 at line 28
use Mail::SpamAssassin::Util;
# spent 96µs making 1 call to Mail::SpamAssassin::NetSet::BEGIN@28 # spent 77µs making 1 call to Exporter::import
29280µs2413µs
# spent 220µs (27+193) within Mail::SpamAssassin::NetSet::BEGIN@29 which was called: # once (27µs+193µs) by Mail::SpamAssassin::Conf::BEGIN@86 at line 29
use Mail::SpamAssassin::Logger;
# spent 220µs making 1 call to Mail::SpamAssassin::NetSet::BEGIN@29 # spent 193µs making 1 call to Exporter::import
30
3112µs
# spent 271µs (32+239) within Mail::SpamAssassin::NetSet::BEGIN@31 which was called: # once (32µs+239µs) by Mail::SpamAssassin::Conf::BEGIN@86 at line 33
use vars qw{
32 @ISA $TESTCODE $NUMTESTS $have_patricia
331133µs2510µs};
# spent 271µs making 1 call to Mail::SpamAssassin::NetSet::BEGIN@31 # spent 239µs making 1 call to vars::import
34
35
# spent 23.0ms (5.04+18.0) within Mail::SpamAssassin::NetSet::BEGIN@35 which was called: # once (5.04ms+18.0ms) by Mail::SpamAssassin::Conf::BEGIN@86 at line 42
BEGIN {
36111µs eval {
371285µs require Net::Patricia;
38134µs116µs Net::Patricia->VERSION(1.16); # need AF_INET6 support
# spent 16µs making 1 call to version::_VERSION
39110µs1173µs import Net::Patricia;
# spent 173µs making 1 call to Exporter::import
4012µs $have_patricia = 1;
41 };
4213.83ms123.0ms}
# spent 23.0ms making 1 call to Mail::SpamAssassin::NetSet::BEGIN@35
43
44###########################################################################
45
46
# spent 282µs (152+130) within Mail::SpamAssassin::NetSet::new which was called 3 times, avg 94µs/call: # 3 times (152µs+130µs) by Mail::SpamAssassin::Conf::new_netset at line 5096 of Mail/SpamAssassin/Conf.pm, avg 94µs/call
sub new {
47320µs my ($class,$netset_name) = @_;
4837µs $class = ref($class) || $class;
49
5035µs $netset_name = '' if !defined $netset_name; # object name for debugging
51326µs my $self = {
52 name => $netset_name, num_nets => 0,
53 cache_hits => 0, cache_attempts => 0,
54 };
55367µs6130µs $self->{pt} = Net::Patricia->new(&AF_INET6) if $have_patricia;
# spent 119µs making 3 calls to Net::Patricia::new, avg 40µs/call # spent 10µs making 3 calls to Socket::AF_INET6, avg 4µs/call
56
5736µs bless $self, $class;
58330µs $self;
59}
60
61###########################################################################
62
63sub DESTROY {
64 my($self) = shift;
65 if (exists $self->{cache}) {
66 local($@, $!, $_); # protect outer layers from a potential surprise
67 my($hits, $attempts) = ($self->{cache_hits}, $self->{cache_attempts});
68 dbg("netset: cache %s hits/attempts: %d/%d, %.1f %%",
69 $self->{name}, $hits, $attempts, 100*$hits/$attempts) if $attempts > 0;
70 }
71}
72
73###########################################################################
74
75
# spent 8.02ms (1.01+7.01) within Mail::SpamAssassin::NetSet::add_cidr which was called 4 times, avg 2.01ms/call: # 2 times (601µs+4.99ms) by Mail::SpamAssassin::Conf::new_netset at line 5098 of Mail/SpamAssassin/Conf.pm, avg 2.79ms/call # 2 times (410µs+2.02ms) by Mail::SpamAssassin::Conf::new_netset at line 5099 of Mail/SpamAssassin/Conf.pm, avg 1.22ms/call
sub add_cidr {
76414µs my ($self, @nets) = @_;
77
78414µs $self->{nets} ||= [ ];
7947µs my $numadded = 0;
8048µs delete $self->{cache}; # invalidate cache (in case of late additions)
81
82414µs foreach my $cidr_orig (@nets) {
8348µs my $cidr = $cidr_orig; # leave original unchanged, useful for logging
84
85 # recognizes syntax:
86 # [IPaddr%scope]/len or IPaddr%scope/len or IPv4addr/mask
87 # optionally prefixed by a '!' to indicate negation (exclusion);
88 # the %scope (i.e. interface), /len or /mask are optional
89
90440µs local($1,$2,$3,$4);
91466µs422µs $cidr =~ s/^\s+//;
# spent 22µs making 4 calls to Mail::SpamAssassin::NetSet::CORE:subst, avg 6µs/call
92460µs49µs my $exclude = ($cidr =~ s/^!\s*//) ? 1 : 0;
# spent 9µs making 4 calls to Mail::SpamAssassin::NetSet::CORE:subst, avg 2µs/call
93
9446µs my $masklen; # netmask or a prefix length
95484µs438µs $masklen = $1 if $cidr =~ s{ / (.*) \z }{}xs;
# spent 38µs making 4 calls to Mail::SpamAssassin::NetSet::CORE:subst, avg 9µs/call
96
97 # discard optional brackets
98448µs49µs $cidr = $1 if $cidr =~ /^ \[ ( [^\]]* ) \] \z/xs;
# spent 9µs making 4 calls to Mail::SpamAssassin::NetSet::CORE:match, avg 2µs/call
99
10046µs my $scope;
101 # IPv6 Scoped Address (RFC 4007, RFC 6874, RFC 3986 "unreserved" charset)
102461µs48µs if ($cidr =~ s/ % ( [A-Z0-9._~-]* ) \z //xsi) { # scope <zone_id> ?
# spent 8µs making 4 calls to Mail::SpamAssassin::NetSet::CORE:subst, avg 2µs/call
103 $scope = $1; # interface specification
104 # discard interface specification, currently just ignored
105 info("netset: ignoring interface scope '%%%s' in IP address %s",
106 $scope, $cidr_orig);
107 }
108
10947µs my $is_ip4 = 0;
110453µs416µs if ($cidr =~ /^ \d+ (\. | \z) /x) { # looks like an IPv4 address
# spent 16µs making 4 calls to Mail::SpamAssassin::NetSet::CORE:match, avg 4µs/call
111231µs215µs if ($cidr =~ /^ (\d+) \. (\d+) \. (\d+) \. (\d+) \z/x) {
# spent 15µs making 2 calls to Mail::SpamAssassin::NetSet::CORE:match, avg 7µs/call
112 # also strips leading zeroes, not liked by inet_pton
113221µs $cidr = sprintf('%d.%d.%d.%d', $1,$2,$3,$4);
11424µs $masklen = 32 if !defined $masklen;
115 } elsif ($cidr =~ /^ (\d+) \. (\d+) \. (\d+) \.? \z/x) {
116 $cidr = sprintf('%d.%d.%d.0', $1,$2,$3);
117 $masklen = 24 if !defined $masklen;
118 } elsif ($cidr =~ /^ (\d+) \. (\d+) \.? \z/x) {
119 $cidr = sprintf('%d.%d.0.0', $1,$2);
120 $masklen = 16 if !defined $masklen;
121 } elsif ($cidr =~ /^ (\d+) \.? \z/x) {
122 $cidr = sprintf('%d.0.0.0', $1);
123 $masklen = 8 if !defined $masklen;
124 } else {
125 warn "netset: illegal IPv4 address given: '$cidr_orig'\n";
126 next;
127 }
128216µs $is_ip4 = 1;
129 }
130
131428µs if ($self->{pt}) {
132411µs if (defined $masklen) {
133240µs218µs $masklen =~ /^\d{1,3}\z/
# spent 18µs making 2 calls to Mail::SpamAssassin::NetSet::CORE:match, avg 9µs/call
134 or die "Network mask not supported, use a CIDR syntax: '$cidr_orig'";
135 }
13648µs my $key = $cidr;
13747µs my $prefix_len = $masklen;
138418µs if ($is_ip4) {
13928µs $key = '::ffff:' . $key; # turn it into an IPv4-mapped IPv6 addresses
14027µs $prefix_len += 96 if defined $prefix_len;
141 }
14248µs $prefix_len = 128 if !defined $prefix_len;
143410µs $key .= '/' . $prefix_len;
144 # dbg("netset: add_cidr (patricia trie) %s => %s",
145 # $cidr_orig, $exclude ? '!'.$key : $key);
146418µs defined eval {
147444µs4755µs $self->{pt}->add_string($key, $exclude ? '!'.$key : $key)
# spent 755µs making 4 calls to Net::Patricia::add_string, avg 189µs/call
148 } or warn "netset: illegal IP address given (patricia trie): ".
149 "'$key': $@\n";
150 }
151
152411µs $cidr .= '/' . $masklen if defined $masklen;
153
154441µs435µs my $ip = NetAddr::IP->new($cidr);
# spent 35µs making 4 calls to NetAddr::IP::Lite::new, avg 9µs/call
15547µs if (!defined $ip) {
156 warn "netset: illegal IP address given: '$cidr_orig'\n";
157 next;
158 }
159 # dbg("netset: add_cidr %s => %s => %s", $cidr_orig, $cidr, $ip);
160
161 # if this is an IPv4 address, create an IPv6 representation, too
16247µs my ($ip4, $ip6);
163414µs if ($is_ip4) {
16424µs $ip4 = $ip;
165216µs22.15ms $ip6 = $self->_convert_ipv4_cidr_to_ipv6($cidr);
# spent 2.15ms making 2 calls to Mail::SpamAssassin::NetSet::_convert_ipv4_cidr_to_ipv6, avg 1.08ms/call
166 } else {
16724µs $ip6 = $ip;
168 }
169
170 # bug 5931: this is O(n^2). bad if there are lots of nets. There are good
171 # reasons to keep it for linting purposes, though, so don't start skipping
172 # it until we have over 200 nets in our list
173829µs if (scalar @{$self->{nets}} < 200) {
174428µs41.80ms next if ($self->is_net_declared($ip4, $ip6, $exclude, 0));
# spent 1.80ms making 4 calls to Mail::SpamAssassin::NetSet::is_net_declared, avg 451µs/call
175 }
176
177 # note: it appears a NetAddr::IP object takes up about 279 bytes
178870µs push @{$self->{nets}}, {
179 exclude => $exclude,
180 ip4 => $ip4,
181 ip6 => $ip6,
182 as_string => $cidr_orig,
183 };
184435µs $numadded++;
185 }
186
18748µs $self->{num_nets} += $numadded;
188453µs $numadded;
189}
190
191sub get_num_nets {
192 my ($self) = @_;
193 return $self->{num_nets};
194}
195
196
# spent 2.15ms (296µs+1.86) within Mail::SpamAssassin::NetSet::_convert_ipv4_cidr_to_ipv6 which was called 2 times, avg 1.08ms/call: # 2 times (296µs+1.86ms) by Mail::SpamAssassin::NetSet::add_cidr at line 165, avg 1.08ms/call
sub _convert_ipv4_cidr_to_ipv6 {
19725µs my ($self, $cidr) = @_;
198
199 # only do this for IPv4 addresses
200230µs27µs return unless $cidr =~ /^\d+[.\/]/;
# spent 7µs making 2 calls to Mail::SpamAssassin::NetSet::CORE:match, avg 4µs/call
201
202225µs26µs if ($cidr !~ /\//) { # no mask
# spent 6µs making 2 calls to Mail::SpamAssassin::NetSet::CORE:match, avg 3µs/call
203 return NetAddr::IP->new6("::ffff:".$cidr);
204 }
205
206 # else we have a CIDR mask specified. use new6() to do this
207 #
2082118µs437µs my $ip6 = ""+(NetAddr::IP->new6($cidr));
# spent 20µs making 2 calls to NetAddr::IP::Lite::plus, avg 10µs/call # spent 16µs making 2 calls to NetAddr::IP::Lite::new6, avg 8µs/call
209 # 127.0.0.1 -> 0:0:0:0:0:0:7F00:0001/128
210 # 127/8 -> 0:0:0:0:0:0:7F00:0/104
211
212 # now, move that from 0:0:0:0:0:0: space to 0:0:0:0:0:ffff: space
213250µs4599µs if (!defined $ip6 || $ip6 !~ /^0:0:0:0:0:0:(.*)$/) {
# spent 312µs making 2 calls to Mail::SpamAssassin::NetSet::CORE:match, avg 156µs/call # spent 286µs making 2 calls to NetAddr::IP::Lite::__ANON__[NetAddr/IP/Lite.pm:238], avg 143µs/call
214 warn "oops! unparseable IPv6 address for $cidr: $ip6";
215 return;
216 }
217
218237µs214µs return NetAddr::IP->new6("::ffff:$1");
# spent 14µs making 2 calls to NetAddr::IP::Lite::new6, avg 7µs/call
219}
220
221
# spent 261µs (125+136) within Mail::SpamAssassin::NetSet::_nets_contains_network which was called 4 times, avg 65µs/call: # 4 times (125µs+136µs) by Mail::SpamAssassin::NetSet::is_net_declared at line 246, avg 65µs/call
sub _nets_contains_network {
22249µs my ($self, $net4, $net6, $exclude, $quiet, $netname, $declared) = @_;
223
22448µs return 0 unless (defined $self->{nets});
225
226840µs foreach my $net (@{$self->{nets}}) {
227 # check to see if the new network is contained by the old network
22825µs my $in4 = defined $net4 && defined $net->{ip4} && $net->{ip4}->contains($net4);
229223µs2136µs my $in6 = defined $net6 && defined $net->{ip6} && $net->{ip6}->contains($net6);
# spent 136µs making 2 calls to NetAddr::IP::Lite::contains, avg 68µs/call
23027µs if ($in4 || $in6) {
231 warn sprintf("netset: cannot %s %s as it has already been %s\n",
232 $exclude ? "exclude" : "include",
233 $netname,
234 $net->{exclude} ? "excluded" : "included") unless $quiet;
235 # a network that matches an excluded network isn't contained by "nets"
236 # return 0 if we're not just looking to see if the network was declared
237 return 0 if (!$declared && $net->{exclude});
238 return 1;
239 }
240 }
241455µs return 0;
242}
243
244
# spent 1.80ms (125µs+1.68) within Mail::SpamAssassin::NetSet::is_net_declared which was called 4 times, avg 451µs/call: # 4 times (125µs+1.68ms) by Mail::SpamAssassin::NetSet::add_cidr at line 174, avg 451µs/call
sub is_net_declared {
245410µs my ($self, $net4, $net6, $exclude, $quiet) = @_;
246497µs61.68ms return $self->_nets_contains_network($net4, $net6, $exclude,
# spent 1.42ms making 2 calls to NetAddr::IP::Lite::__ANON__[NetAddr/IP/Lite.pm:238], avg 708µs/call # spent 261µs making 4 calls to Mail::SpamAssassin::NetSet::_nets_contains_network, avg 65µs/call
247 $quiet, $net4 || $net6, 1);
248}
249
250sub contains_ip {
251 my ($self, $ip) = @_;
252 my $result = 0;
253
254 if (!$self->{num_nets}) { return 0 }
255
256 $self->{cache_attempts}++;
257 if ($self->{cache} && exists $self->{cache}{$ip}) {
258 dbg("netset: %s cached lookup on %s, %d networks, result: %s",
259 $self->{name}, $ip, $self->{num_nets}, $self->{cache}{$ip});
260 $self->{cache_hits}++;
261 return $self->{cache}{$ip};
262
263 } elsif ($self->{pt}) {
264 # do a quick lookup on a Patricia Trie
265 my $t0 = time;
266 local($1,$2,$3,$4); local $_ = $ip;
267 $_ = $1 if /^ \[ ( [^\]]* ) \] \z/xs; # discard optional brackets
268 s/%[A-Z0-9:._-]+\z//si; # discard interface specification
269 if (m{^ (\d+) \. (\d+) \. (\d+) \. (\d+) \z}x) {
270 $_ = sprintf('::ffff:%d.%d.%d.%d', $1,$2,$3,$4);
271 } else {
272 s/^IPv6://si; # discard optional 'IPv6:' prefix
273 }
274 eval { $result = $self->{pt}->match_string($_); 1 } or undef $result;
275 $result = defined $result && $result !~ /^!/ ? 1 : 0;
276 dbg("netset: %s patricia lookup on %s, %d networks, result: %s, %.3f ms",
277 $self->{name}, $ip, $self->{num_nets}, $result, 1000*(time - $t0));
278 } else {
279 # do a sequential search on a list of NetAddr::IP objects
280 my $t0 = time;
281 my ($ip4, $ip6);
282 if ($ip =~ /^\d+\./) {
283 $ip4 = NetAddr::IP->new($ip);
284 $ip6 = $self->_convert_ipv4_cidr_to_ipv6($ip);
285 } else {
286 $ip6 = NetAddr::IP->new($ip);
287 }
288 foreach my $net (@{$self->{nets}}) {
289 if ((defined $ip4 && defined $net->{ip4} && $net->{ip4}->contains($ip4))
290 || (defined $ip6 && defined $net->{ip6} && $net->{ip6}->contains($ip6))){
291 $result = !$net->{exclude};
292 last;
293 }
294 }
295 dbg("netset: %s lookup on %s, %d networks, result: %s, %.3f ms",
296 $self->{name}, $ip, $self->{num_nets}, $result, 1000*(time - $t0));
297 }
298
299 $self->{cache}{$ip} = $result;
300 return $result;
301}
302
303sub contains_net {
304 my ($self, $net) = @_;
305 my $exclude = $net->{exclude};
306 my $net4 = $net->{ip4};
307 my $net6 = $net->{ip6};
308 return $self->_nets_contains_network($net4, $net6, $exclude, 1, "", 0);
309}
310
311sub ditch_cache {
312 my ($self) = @_;
313 if (exists $self->{cache}) {
314 dbg("netset: ditch cache on %s", $self->{name});
315 delete $self->{cache};
316 }
317}
318
319sub clone {
320 my ($self) = @_;
321 my $dup = Mail::SpamAssassin::NetSet->new($self->{name});
322 if ($self->{nets}) {
323 @{$dup->{nets}} = @{$self->{nets}};
324 }
325 if ($self->{pt}) {
326 my $dup_pt = $dup->{pt};
327 $self->{pt}->climb(sub {
328 my $key = $_[0]; $key =~ s/^!//;
329 defined eval { $dup_pt->add_string($key, $_[0]) }
330 or die "Adding a network $_[0] to a patricia trie failed: $@";
331 1;
332 });
333 }
334 $dup->{num_nets} = $self->{num_nets};
335 return $dup;
336}
337
338###########################################################################
339
340113µs1;
 
# spent 383µs (97+286) within Mail::SpamAssassin::NetSet::CORE:match which was called 18 times, avg 21µs/call: # 4 times (16µs+0s) by Mail::SpamAssassin::NetSet::add_cidr at line 110, avg 4µs/call # 4 times (9µs+0s) by Mail::SpamAssassin::NetSet::add_cidr at line 98, avg 2µs/call # 2 times (26µs+286µs) by Mail::SpamAssassin::NetSet::_convert_ipv4_cidr_to_ipv6 at line 213, avg 156µs/call # 2 times (18µs+0s) by Mail::SpamAssassin::NetSet::add_cidr at line 133, avg 9µs/call # 2 times (15µs+0s) by Mail::SpamAssassin::NetSet::add_cidr at line 111, avg 7µs/call # 2 times (7µs+0s) by Mail::SpamAssassin::NetSet::_convert_ipv4_cidr_to_ipv6 at line 200, avg 4µs/call # 2 times (6µs+0s) by Mail::SpamAssassin::NetSet::_convert_ipv4_cidr_to_ipv6 at line 202, avg 3µs/call
sub Mail::SpamAssassin::NetSet::CORE:match; # opcode
# spent 77µs within Mail::SpamAssassin::NetSet::CORE:subst which was called 16 times, avg 5µs/call: # 4 times (38µs+0s) by Mail::SpamAssassin::NetSet::add_cidr at line 95, avg 9µs/call # 4 times (22µs+0s) by Mail::SpamAssassin::NetSet::add_cidr at line 91, avg 6µs/call # 4 times (9µs+0s) by Mail::SpamAssassin::NetSet::add_cidr at line 92, avg 2µs/call # 4 times (8µs+0s) by Mail::SpamAssassin::NetSet::add_cidr at line 102, avg 2µs/call
sub Mail::SpamAssassin::NetSet::CORE:subst; # opcode