mirror of
https://github.com/nmap/nmap.git
synced 2025-12-06 12:41:29 +00:00
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)
This commit is contained in:
@@ -2437,14 +2437,18 @@ static void retransmitProbe(UltraScanInfo *USI, HostScanStats *hss,
|
|||||||
USI->gstats->probes_sent++;
|
USI->gstats->probes_sent++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct ProbeCacheNode {
|
||||||
|
HostScanStats *hss;
|
||||||
|
std::list<UltraProbe *>::iterator probeI;
|
||||||
|
};
|
||||||
|
|
||||||
/* Go through the ProbeQueue of each host, identify any
|
/* Go through the ProbeQueue of each host, identify any
|
||||||
timed out probes, then try to retransmit them as appropriate */
|
timed out probes, then try to retransmit them as appropriate */
|
||||||
static void doAnyOutstandingRetransmits(UltraScanInfo *USI) {
|
static void doAnyOutstandingRetransmits(UltraScanInfo *USI) {
|
||||||
std::multiset<HostScanStats *, HssPredicate>::iterator hostI;
|
std::multiset<HostScanStats *, HssPredicate>::iterator hostI;
|
||||||
std::list<UltraProbe *>::iterator probeI;
|
|
||||||
/* A cache of the last processed probe from each host, to avoid re-examining a
|
/* A cache of the last processed probe from each host, to avoid re-examining a
|
||||||
bunch of probes to find the next one that needs to be retransmitted. */
|
bunch of probes to find the next one that needs to be retransmitted. */
|
||||||
std::map<HostScanStats *, std::list<UltraProbe *>::iterator> probe_cache;
|
std::vector<struct ProbeCacheNode> probe_cache;
|
||||||
HostScanStats *host = NULL;
|
HostScanStats *host = NULL;
|
||||||
UltraProbe *probe = NULL;
|
UltraProbe *probe = NULL;
|
||||||
int retrans = 0; /* Number of retransmissions during a loop */
|
int retrans = 0; /* Number of retransmissions during a loop */
|
||||||
@@ -2457,14 +2461,29 @@ static void doAnyOutstandingRetransmits(UltraScanInfo *USI) {
|
|||||||
if (o.debugging)
|
if (o.debugging)
|
||||||
tv_start = USI->now;
|
tv_start = USI->now;
|
||||||
|
|
||||||
|
probe_cache.reserve(USI->numIncompleteHosts());
|
||||||
|
for (hostI = USI->incompleteHosts.begin();
|
||||||
|
hostI != USI->incompleteHosts.end();
|
||||||
|
hostI++) {
|
||||||
|
struct ProbeCacheNode pcn;
|
||||||
|
pcn.hss = *hostI;
|
||||||
|
/* Skip this host if it has nothing to send. */
|
||||||
|
if (pcn.hss->num_probes_active == 0
|
||||||
|
&& pcn.hss->num_probes_waiting_retransmit == 0)
|
||||||
|
continue;
|
||||||
|
assert(!pcn.hss->probes_outstanding.empty());
|
||||||
|
pcn.probeI = pcn.hss->probes_outstanding.end();
|
||||||
|
probe_cache.push_back(pcn);
|
||||||
|
}
|
||||||
/* Loop until we get through all the hosts without a retransmit or we're not
|
/* Loop until we get through all the hosts without a retransmit or we're not
|
||||||
OK to send any more. */
|
OK to send any more. */
|
||||||
do {
|
do {
|
||||||
retrans = 0;
|
retrans = 0;
|
||||||
for (hostI = USI->incompleteHosts.begin();
|
for (std::vector<struct ProbeCacheNode>::iterator pci = probe_cache.begin();
|
||||||
hostI != USI->incompleteHosts.end() && USI->gstats->sendOK(NULL);
|
pci != probe_cache.end() && USI->gstats->sendOK(NULL);
|
||||||
hostI++) {
|
pci++) {
|
||||||
host = *hostI;
|
host = pci->hss;
|
||||||
|
std::list<UltraProbe *>::iterator &probeI = pci->probeI;
|
||||||
/* Skip this host if it has nothing to send. */
|
/* Skip this host if it has nothing to send. */
|
||||||
if ((host->num_probes_active == 0
|
if ((host->num_probes_active == 0
|
||||||
&& host->num_probes_waiting_retransmit == 0))
|
&& host->num_probes_waiting_retransmit == 0))
|
||||||
@@ -2473,12 +2492,6 @@ static void doAnyOutstandingRetransmits(UltraScanInfo *USI) {
|
|||||||
continue;
|
continue;
|
||||||
assert(!host->probes_outstanding.empty());
|
assert(!host->probes_outstanding.empty());
|
||||||
|
|
||||||
/* Initialize the probe cache if necessary. */
|
|
||||||
if (probe_cache.find(host) == probe_cache.end())
|
|
||||||
probe_cache[host] = host->probes_outstanding.end();
|
|
||||||
/* Restore the probe iterator from the cache. */
|
|
||||||
probeI = probe_cache[host];
|
|
||||||
|
|
||||||
maxtries = host->allowedTryno(NULL, NULL);
|
maxtries = host->allowedTryno(NULL, NULL);
|
||||||
do {
|
do {
|
||||||
probeI--;
|
probeI--;
|
||||||
@@ -2508,8 +2521,6 @@ static void doAnyOutstandingRetransmits(UltraScanInfo *USI) {
|
|||||||
/* Wrap the probe iterator around. */
|
/* Wrap the probe iterator around. */
|
||||||
if (probeI == host->probes_outstanding.begin())
|
if (probeI == host->probes_outstanding.begin())
|
||||||
probeI = host->probes_outstanding.end();
|
probeI = host->probes_outstanding.end();
|
||||||
/* Cache the probe iterator. */
|
|
||||||
probe_cache[host] = probeI;
|
|
||||||
}
|
}
|
||||||
} while (USI->gstats->sendOK(NULL) && retrans != 0);
|
} while (USI->gstats->sendOK(NULL) && retrans != 0);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user