← Index
NYTProf Performance Profile   « line view »
For /usr/local/bin/sa-learn
  Run on Sun Nov 5 03:09:29 2017
Reported on Mon Nov 6 13:20:46 2017

Filename/usr/local/lib/perl5/site_perl/Mail/SpamAssassin/NetSet.pm
StatementsExecuted 264 statements in 6.05ms
Subroutines
Calls P F Exclusive
Time
Inclusive
Time
Subroutine
1114.62ms20.1msMail::SpamAssassin::NetSet::::BEGIN@35Mail::SpamAssassin::NetSet::BEGIN@35
421808µs6.39msMail::SpamAssassin::NetSet::::add_cidrMail::SpamAssassin::NetSet::add_cidr
211234µs1.65msMail::SpamAssassin::NetSet::::_convert_ipv4_cidr_to_ipv6Mail::SpamAssassin::NetSet::_convert_ipv4_cidr_to_ipv6
311116µs240µsMail::SpamAssassin::NetSet::::newMail::SpamAssassin::NetSet::new
411107µs232µsMail::SpamAssassin::NetSet::::_nets_contains_networkMail::SpamAssassin::NetSet::_nets_contains_network
187184µs304µsMail::SpamAssassin::NetSet::::CORE:matchMail::SpamAssassin::NetSet::CORE:match (opcode)
41171µs1.62msMail::SpamAssassin::NetSet::::is_net_declaredMail::SpamAssassin::NetSet::is_net_declared
164168µs68µsMail::SpamAssassin::NetSet::::CORE:substMail::SpamAssassin::NetSet::CORE:subst (opcode)
11141µs49µsMail::SpamAssassin::NetSet::::BEGIN@21Mail::SpamAssassin::NetSet::BEGIN@21
11136µs432µsMail::SpamAssassin::NetSet::::BEGIN@26Mail::SpamAssassin::NetSet::BEGIN@26
11128µs157µsMail::SpamAssassin::NetSet::::BEGIN@29Mail::SpamAssassin::NetSet::BEGIN@29
11127µs799µsMail::SpamAssassin::NetSet::::BEGIN@25Mail::SpamAssassin::NetSet::BEGIN@25
11126µs59µsMail::SpamAssassin::NetSet::::BEGIN@22Mail::SpamAssassin::NetSet::BEGIN@22
11125µs91µsMail::SpamAssassin::NetSet::::BEGIN@24Mail::SpamAssassin::NetSet::BEGIN@24
11124µs31µsMail::SpamAssassin::NetSet::::BEGIN@23Mail::SpamAssassin::NetSet::BEGIN@23
11121µs198µsMail::SpamAssassin::NetSet::::BEGIN@31Mail::SpamAssassin::NetSet::BEGIN@31
11120µs76µ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
21261µs258µs
# spent 49µs (41+9) within Mail::SpamAssassin::NetSet::BEGIN@21 which was called: # once (41µs+9µs) by Mail::SpamAssassin::Conf::BEGIN@86 at line 21
use strict;
# spent 49µs making 1 call to Mail::SpamAssassin::NetSet::BEGIN@21 # spent 9µs making 1 call to strict::import
22254µs291µs
# spent 59µs (26+32) within Mail::SpamAssassin::NetSet::BEGIN@22 which was called: # once (26µs+32µs) by Mail::SpamAssassin::Conf::BEGIN@86 at line 22
use warnings;
# spent 59µs making 1 call to Mail::SpamAssassin::NetSet::BEGIN@22 # spent 32µs making 1 call to warnings::import
23257µs237µs
# spent 31µs (24+7) within Mail::SpamAssassin::NetSet::BEGIN@23 which was called: # once (24µs+7µs) by Mail::SpamAssassin::Conf::BEGIN@86 at line 23
use bytes;
# spent 31µs making 1 call to Mail::SpamAssassin::NetSet::BEGIN@23 # spent 7µs making 1 call to bytes::import
24264µs2157µs
# spent 91µs (25+66) within Mail::SpamAssassin::NetSet::BEGIN@24 which was called: # once (25µs+66µs) by Mail::SpamAssassin::Conf::BEGIN@86 at line 24
use re 'taint';
# spent 91µs making 1 call to Mail::SpamAssassin::NetSet::BEGIN@24 # spent 66µs making 1 call to re::import
25269µs21.57ms
# spent 799µs (27+772) within Mail::SpamAssassin::NetSet::BEGIN@25 which was called: # once (27µs+772µs) by Mail::SpamAssassin::Conf::BEGIN@86 at line 25
use Time::HiRes qw(time);
# spent 799µs making 1 call to Mail::SpamAssassin::NetSet::BEGIN@25 # spent 772µs making 1 call to Time::HiRes::import
26399µs3827µs
# spent 432µs (36+396) within Mail::SpamAssassin::NetSet::BEGIN@26 which was called: # once (36µs+396µs) by Mail::SpamAssassin::Conf::BEGIN@86 at line 26
use NetAddr::IP 4.000;
# spent 432µs making 1 call to Mail::SpamAssassin::NetSet::BEGIN@26 # spent 377µs making 1 call to NetAddr::IP::import # spent 19µs making 1 call to UNIVERSAL::VERSION
27
28254µs2131µs
# spent 76µs (20+56) within Mail::SpamAssassin::NetSet::BEGIN@28 which was called: # once (20µs+56µs) by Mail::SpamAssassin::Conf::BEGIN@86 at line 28
use Mail::SpamAssassin::Util;
# spent 76µs making 1 call to Mail::SpamAssassin::NetSet::BEGIN@28 # spent 56µs making 1 call to Exporter::import
29270µs2286µs
# spent 157µs (28+129) within Mail::SpamAssassin::NetSet::BEGIN@29 which was called: # once (28µs+129µs) by Mail::SpamAssassin::Conf::BEGIN@86 at line 29
use Mail::SpamAssassin::Logger;
# spent 157µs making 1 call to Mail::SpamAssassin::NetSet::BEGIN@29 # spent 129µs making 1 call to Exporter::import
30
3112µs
# spent 198µs (21+177) within Mail::SpamAssassin::NetSet::BEGIN@31 which was called: # once (21µs+177µs) by Mail::SpamAssassin::Conf::BEGIN@86 at line 33
use vars qw{
32 @ISA $TESTCODE $NUMTESTS $have_patricia
331118µs2375µs};
# spent 198µs making 1 call to Mail::SpamAssassin::NetSet::BEGIN@31 # spent 177µs making 1 call to vars::import
34
35
# spent 20.1ms (4.62+15.5) within Mail::SpamAssassin::NetSet::BEGIN@35 which was called: # once (4.62ms+15.5ms) by Mail::SpamAssassin::Conf::BEGIN@86 at line 42
BEGIN {
36111µs eval {
371288µ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µs1118µs import Net::Patricia;
# spent 118µs making 1 call to Exporter::import
4013µs $have_patricia = 1;
41 };
4213.62ms120.1ms}
# spent 20.1ms making 1 call to Mail::SpamAssassin::NetSet::BEGIN@35
43
44###########################################################################
45
46
# spent 240µs (116+124) within Mail::SpamAssassin::NetSet::new which was called 3 times, avg 80µs/call: # 3 times (116µs+124µs) by Mail::SpamAssassin::Conf::new_netset at line 5096 of Mail/SpamAssassin/Conf.pm, avg 80µs/call
sub new {
4736µs my ($class,$netset_name) = @_;
4837µs $class = ref($class) || $class;
49
5036µs $netset_name = '' if !defined $netset_name; # object name for debugging
51316µs my $self = {
52 name => $netset_name, num_nets => 0,
53 cache_hits => 0, cache_attempts => 0,
54 };
55368µs6124µs $self->{pt} = Net::Patricia->new(&AF_INET6) if $have_patricia;
# spent 113µs making 3 calls to Net::Patricia::new, avg 38µs/call # spent 11µs making 3 calls to Socket::AF_INET6, avg 4µs/call
56
5736µs bless $self, $class;
58320µ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 6.39ms (808µs+5.58) within Mail::SpamAssassin::NetSet::add_cidr which was called 4 times, avg 1.60ms/call: # 2 times (519µs+4.21ms) by Mail::SpamAssassin::Conf::new_netset at line 5098 of Mail/SpamAssassin/Conf.pm, avg 2.36ms/call # 2 times (288µs+1.37ms) by Mail::SpamAssassin::Conf::new_netset at line 5099 of Mail/SpamAssassin/Conf.pm, avg 831µs/call
sub add_cidr {
76412µs my ($self, @nets) = @_;
77
78414µs $self->{nets} ||= [ ];
7947µs my $numadded = 0;
8049µ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
90424µs local($1,$2,$3,$4);
91454µs423µs $cidr =~ s/^\s+//;
# spent 23µs making 4 calls to Mail::SpamAssassin::NetSet::CORE:subst, avg 6µs/call
92440µs410µs my $exclude = ($cidr =~ s/^!\s*//) ? 1 : 0;
# spent 10µs making 4 calls to Mail::SpamAssassin::NetSet::CORE:subst, avg 2µs/call
93
9446µs my $masklen; # netmask or a prefix length
95456µs428µs $masklen = $1 if $cidr =~ s{ / (.*) \z }{}xs;
# spent 28µs making 4 calls to Mail::SpamAssassin::NetSet::CORE:subst, avg 7µs/call
96
97 # discard optional brackets
98436µs411µs $cidr = $1 if $cidr =~ /^ \[ ( [^\]]* ) \] \z/xs;
# spent 11µs making 4 calls to Mail::SpamAssassin::NetSet::CORE:match, avg 3µs/call
99
10046µs my $scope;
101 # IPv6 Scoped Address (RFC 4007, RFC 6874, RFC 3986 "unreserved" charset)
102430µ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;
110438µs412µs if ($cidr =~ /^ \d+ (\. | \z) /x) { # looks like an IPv4 address
# spent 12µs making 4 calls to Mail::SpamAssassin::NetSet::CORE:match, avg 3µs/call
111229µs213µs if ($cidr =~ /^ (\d+) \. (\d+) \. (\d+) \. (\d+) \z/x) {
# spent 13µs making 2 calls to Mail::SpamAssassin::NetSet::CORE:match, avg 7µs/call
112 # also strips leading zeroes, not liked by inet_pton
113230µ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 }
12824µs $is_ip4 = 1;
129 }
130
131427µs if ($self->{pt}) {
132410µs if (defined $masklen) {
133230µs29µs $masklen =~ /^\d{1,3}\z/
# spent 9µs making 2 calls to Mail::SpamAssassin::NetSet::CORE:match, avg 5µ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;
138410µs if ($is_ip4) {
13928µs $key = '::ffff:' . $key; # turn it into an IPv4-mapped IPv6 addresses
14026µs $prefix_len += 96 if defined $prefix_len;
141 }
14248µs $prefix_len = 128 if !defined $prefix_len;
14349µs $key .= '/' . $prefix_len;
144 # dbg("netset: add_cidr (patricia trie) %s => %s",
145 # $cidr_orig, $exclude ? '!'.$key : $key);
146416µs defined eval {
147442µs4696µs $self->{pt}->add_string($key, $exclude ? '!'.$key : $key)
# spent 696µs making 4 calls to Net::Patricia::add_string, avg 174µ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
154440µs436µs my $ip = NetAddr::IP->new($cidr);
# spent 36µ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);
163413µs if ($is_ip4) {
16424µs $ip4 = $ip;
165217µs21.65ms $ip6 = $self->_convert_ipv4_cidr_to_ipv6($cidr);
# spent 1.65ms making 2 calls to Mail::SpamAssassin::NetSet::_convert_ipv4_cidr_to_ipv6, avg 827µs/call
166 } else {
16723µ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
173830µs if (scalar @{$self->{nets}} < 200) {
174429µs41.62ms next if ($self->is_net_declared($ip4, $ip6, $exclude, 0));
# spent 1.62ms making 4 calls to Mail::SpamAssassin::NetSet::is_net_declared, avg 405µs/call
175 }
176
177 # note: it appears a NetAddr::IP object takes up about 279 bytes
178847µs push @{$self->{nets}}, {
179 exclude => $exclude,
180 ip4 => $ip4,
181 ip6 => $ip6,
182 as_string => $cidr_orig,
183 };
184429µs $numadded++;
185 }
186
18748µs $self->{num_nets} += $numadded;
188428µs $numadded;
189}
190
191sub get_num_nets {
192 my ($self) = @_;
193 return $self->{num_nets};
194}
195
196
# spent 1.65ms (234µs+1.42) within Mail::SpamAssassin::NetSet::_convert_ipv4_cidr_to_ipv6 which was called 2 times, avg 827µs/call: # 2 times (234µs+1.42ms) by Mail::SpamAssassin::NetSet::add_cidr at line 165, avg 827µs/call
sub _convert_ipv4_cidr_to_ipv6 {
19725µs my ($self, $cidr) = @_;
198
199 # only do this for IPv4 addresses
200221µs27µs return unless $cidr =~ /^\d+[.\/]/;
# spent 7µs making 2 calls to Mail::SpamAssassin::NetSet::CORE:match, avg 4µs/call
201
202218µ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 #
2082123µs436µs my $ip6 = ""+(NetAddr::IP->new6($cidr));
# spent 19µs making 2 calls to NetAddr::IP::Lite::plus, avg 10µs/call # spent 17µs making 2 calls to NetAddr::IP::Lite::new6, avg 9µ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
213236µs4467µs if (!defined $ip6 || $ip6 !~ /^0:0:0:0:0:0:(.*)$/) {
# spent 246µs making 2 calls to Mail::SpamAssassin::NetSet::CORE:match, avg 123µs/call # spent 221µs making 2 calls to NetAddr::IP::Lite::__ANON__[NetAddr/IP/Lite.pm:238], avg 110µs/call
214 warn "oops! unparseable IPv6 address for $cidr: $ip6";
215 return;
216 }
217
218236µ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 232µs (107+125) within Mail::SpamAssassin::NetSet::_nets_contains_network which was called 4 times, avg 58µs/call: # 4 times (107µs+125µs) by Mail::SpamAssassin::NetSet::is_net_declared at line 246, avg 58µs/call
sub _nets_contains_network {
22248µs my ($self, $net4, $net6, $exclude, $quiet, $netname, $declared) = @_;
223
22448µs return 0 unless (defined $self->{nets});
225
226830µ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);
229222µs2125µs my $in6 = defined $net6 && defined $net->{ip6} && $net->{ip6}->contains($net6);
# spent 125µs making 2 calls to NetAddr::IP::Lite::contains, avg 62µ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 }
241426µs return 0;
242}
243
244
# spent 1.62ms (71µs+1.55) within Mail::SpamAssassin::NetSet::is_net_declared which was called 4 times, avg 405µs/call: # 4 times (71µs+1.55ms) by Mail::SpamAssassin::NetSet::add_cidr at line 174, avg 405µs/call
sub is_net_declared {
24549µs my ($self, $net4, $net6, $exclude, $quiet) = @_;
246457µs61.55ms return $self->_nets_contains_network($net4, $net6, $exclude,
# spent 1.32ms making 2 calls to NetAddr::IP::Lite::__ANON__[NetAddr/IP/Lite.pm:238], avg 659µs/call # spent 232µs making 4 calls to Mail::SpamAssassin::NetSet::_nets_contains_network, avg 58µ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
34018µs1;
 
# spent 304µs (84+221) within Mail::SpamAssassin::NetSet::CORE:match which was called 18 times, avg 17µs/call: # 4 times (12µs+0s) by Mail::SpamAssassin::NetSet::add_cidr at line 110, avg 3µs/call # 4 times (11µs+0s) by Mail::SpamAssassin::NetSet::add_cidr at line 98, avg 3µs/call # 2 times (25µs+221µs) by Mail::SpamAssassin::NetSet::_convert_ipv4_cidr_to_ipv6 at line 213, avg 123µs/call # 2 times (13µs+0s) by Mail::SpamAssassin::NetSet::add_cidr at line 111, avg 7µs/call # 2 times (9µs+0s) by Mail::SpamAssassin::NetSet::add_cidr at line 133, avg 5µ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 68µs within Mail::SpamAssassin::NetSet::CORE:subst which was called 16 times, avg 4µs/call: # 4 times (28µs+0s) by Mail::SpamAssassin::NetSet::add_cidr at line 95, avg 7µs/call # 4 times (23µs+0s) by Mail::SpamAssassin::NetSet::add_cidr at line 91, avg 6µs/call # 4 times (10µ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