Skip to content

Commit ee059c4

Browse files
committed
Big optimization of doAnyOutstandingRetransmits
Retransmitting does not change the set of incomplete hosts, so there's no need to use a map to store the current position in the outstanding probes queue. Using a vector is much faster. Additionally, improper use of std::map::find() and std::map::operator[] meant that the O(logN) lookup was happening 4 times for a single host for each iteration through the loop. Complexity for N targets is now O(N), not O(N logN)
1 parent a2062c2 commit ee059c4

File tree

1 file changed

+25
-14
lines changed

1 file changed

+25
-14
lines changed

scan_engine.cc

+25-14
Original file line numberDiff line numberDiff line change
@@ -2437,14 +2437,18 @@ static void retransmitProbe(UltraScanInfo *USI, HostScanStats *hss,
24372437
USI->gstats->probes_sent++;
24382438
}
24392439

2440+
struct ProbeCacheNode {
2441+
HostScanStats *hss;
2442+
std::list<UltraProbe *>::iterator probeI;
2443+
};
2444+
24402445
/* Go through the ProbeQueue of each host, identify any
24412446
timed out probes, then try to retransmit them as appropriate */
24422447
static void doAnyOutstandingRetransmits(UltraScanInfo *USI) {
24432448
std::multiset<HostScanStats *, HssPredicate>::iterator hostI;
2444-
std::list<UltraProbe *>::iterator probeI;
24452449
/* A cache of the last processed probe from each host, to avoid re-examining a
24462450
bunch of probes to find the next one that needs to be retransmitted. */
2447-
std::map<HostScanStats *, std::list<UltraProbe *>::iterator> probe_cache;
2451+
std::vector<struct ProbeCacheNode> probe_cache;
24482452
HostScanStats *host = NULL;
24492453
UltraProbe *probe = NULL;
24502454
int retrans = 0; /* Number of retransmissions during a loop */
@@ -2457,14 +2461,29 @@ static void doAnyOutstandingRetransmits(UltraScanInfo *USI) {
24572461
if (o.debugging)
24582462
tv_start = USI->now;
24592463

2464+
probe_cache.reserve(USI->numIncompleteHosts());
2465+
for (hostI = USI->incompleteHosts.begin();
2466+
hostI != USI->incompleteHosts.end();
2467+
hostI++) {
2468+
struct ProbeCacheNode pcn;
2469+
pcn.hss = *hostI;
2470+
/* Skip this host if it has nothing to send. */
2471+
if (pcn.hss->num_probes_active == 0
2472+
&& pcn.hss->num_probes_waiting_retransmit == 0)
2473+
continue;
2474+
assert(!pcn.hss->probes_outstanding.empty());
2475+
pcn.probeI = pcn.hss->probes_outstanding.end();
2476+
probe_cache.push_back(pcn);
2477+
}
24602478
/* Loop until we get through all the hosts without a retransmit or we're not
24612479
OK to send any more. */
24622480
do {
24632481
retrans = 0;
2464-
for (hostI = USI->incompleteHosts.begin();
2465-
hostI != USI->incompleteHosts.end() && USI->gstats->sendOK(NULL);
2466-
hostI++) {
2467-
host = *hostI;
2482+
for (std::vector<struct ProbeCacheNode>::iterator pci = probe_cache.begin();
2483+
pci != probe_cache.end() && USI->gstats->sendOK(NULL);
2484+
pci++) {
2485+
host = pci->hss;
2486+
std::list<UltraProbe *>::iterator &probeI = pci->probeI;
24682487
/* Skip this host if it has nothing to send. */
24692488
if ((host->num_probes_active == 0
24702489
&& host->num_probes_waiting_retransmit == 0))
@@ -2473,12 +2492,6 @@ static void doAnyOutstandingRetransmits(UltraScanInfo *USI) {
24732492
continue;
24742493
assert(!host->probes_outstanding.empty());
24752494

2476-
/* Initialize the probe cache if necessary. */
2477-
if (probe_cache.find(host) == probe_cache.end())
2478-
probe_cache[host] = host->probes_outstanding.end();
2479-
/* Restore the probe iterator from the cache. */
2480-
probeI = probe_cache[host];
2481-
24822495
maxtries = host->allowedTryno(NULL, NULL);
24832496
do {
24842497
probeI--;
@@ -2508,8 +2521,6 @@ static void doAnyOutstandingRetransmits(UltraScanInfo *USI) {
25082521
/* Wrap the probe iterator around. */
25092522
if (probeI == host->probes_outstanding.begin())
25102523
probeI = host->probes_outstanding.end();
2511-
/* Cache the probe iterator. */
2512-
probe_cache[host] = probeI;
25132524
}
25142525
} while (USI->gstats->sendOK(NULL) && retrans != 0);
25152526

0 commit comments

Comments
 (0)