mirror of
https://github.com/nmap/nmap.git
synced 2025-12-25 00:49:01 +00:00
Merge from /nmap-exp/david/nmap-fixed-rate. This brings in
doAnyOutstandingProbes performance improvements. Here is the log message from r7914 in nmap-fixed-rate. Keep a cache of the most recently processed probe for each host in doAnyOutstandingRetransmits. This greatly reduces the amount of CPU used by that function when the lists of outstanding probes grow long, such as when a high scan rate is specified with --min-rate. This is not most efficient possible way this could be done, but it is a pretty big win, and it's very non-invasive. The changes are limited entirely to doAnyOutstandingRetransmits, with no new global state in ultra_scan. # nmap -d --min-rate 50000 -n -PN -p1-65535 --max-rtt-timeout 500 --max-retries 1 scanme.nmap.org gprof before: % cumulative self self total time seconds seconds calls s/call s/call name 49.74 30.96 30.96 2709 0.01 0.02 doAnyOutstandingRetransmits(UltraScanInfo*) 10.51 37.50 6.54 127256413 0.00 0.00 std::_List_iterator<UltraProbe*>::operator--(int) gprof after: % cumulative self self total time seconds seconds calls s/call s/call name 20.48 3.36 3.36 2667 0.00 0.00 doAnyOutstandingRetransmits(UltraScanInfo*) 16.21 6.02 2.66 2667 0.00 0.00 processData(UltraScanInfo*) Note that 50000 packets per second is way excessive. I really only get about 6000 in practice. But the point is there is no huge CPU penalty for giving an excessive rate.
This commit is contained in:
@@ -114,6 +114,7 @@
|
||||
#include "targets.h"
|
||||
#include "utils.h"
|
||||
#include <list>
|
||||
#include <map>
|
||||
|
||||
using namespace std;
|
||||
extern NmapOps o;
|
||||
@@ -3048,6 +3049,9 @@ static void retransmitProbe(UltraScanInfo *USI, HostScanStats *hss,
|
||||
static void doAnyOutstandingRetransmits(UltraScanInfo *USI) {
|
||||
list<HostScanStats *>::iterator hostI;
|
||||
list<UltraProbe *>::iterator probeI;
|
||||
/* 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. */
|
||||
map<HostScanStats *, list<UltraProbe *>::iterator> probe_cache;
|
||||
HostScanStats *host = NULL;
|
||||
UltraProbe *probe = NULL;
|
||||
int retrans = 0; /* Number of retransmissions during a loop */
|
||||
@@ -3076,7 +3080,13 @@ static void doAnyOutstandingRetransmits(UltraScanInfo *USI) {
|
||||
if (!host->sendOK(NULL))
|
||||
continue;
|
||||
assert(!host->probes_outstanding.empty());
|
||||
probeI = host->probes_outstanding.end();
|
||||
|
||||
/* 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);
|
||||
do {
|
||||
probeI--;
|
||||
@@ -3098,6 +3108,12 @@ static void doAnyOutstandingRetransmits(UltraScanInfo *USI) {
|
||||
break; /* I only do one probe per host for now to spread load */
|
||||
}
|
||||
} while (probeI != host->probes_outstanding.begin());
|
||||
|
||||
/* Wrap the probe iterator around. */
|
||||
if (probeI == host->probes_outstanding.begin())
|
||||
probeI = host->probes_outstanding.end();
|
||||
/* Cache the probe iterator. */
|
||||
probe_cache[host] = probeI;
|
||||
}
|
||||
} while (USI->gstats->sendOK(NULL) && retrans != 0);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user