Expose new --mmap switch (mmap_memory: true in NodeJS), and run test suite in this mode, as well as shared memory mode.

This commit is contained in:
Daniel Patterson 2018-10-26 23:50:46 -07:00
parent 2f9cb44368
commit b7e7d32361
No known key found for this signature in database
GPG Key ID: 19C12BE1725A028B
9 changed files with 91 additions and 12 deletions

View File

@ -1,5 +1,8 @@
# UNRELEASED # UNRELEASED
- Changes from 5.19.0: - Changes from 5.19.0:
- Features:
- ADDED: direct mmapping of datafiles is now supported via the `-mmap` switch. [#5242](https://github.com/Project-OSRM/osrm-backend/pull/5242)
- REMOVED: the previous `--memory_file` switch is now deprecated and will fallback to `--mmap` [#5242](https://github.com/Project-OSRM/osrm-backend/pull/5242)
# 5.19.0 # 5.19.0
- Changes from 5.18.0: - Changes from 5.18.0:

View File

@ -84,7 +84,47 @@ class OSRMDirectLoader extends OSRMBaseLoader {
throw new Error(util.format('osrm-routed %s: %s', errorReason(err), err.cmd)); throw new Error(util.format('osrm-routed %s: %s', errorReason(err), err.cmd));
} }
}); });
callback();
this.child.readyFunc = (data) => {
if (/running and waiting for requests/.test(data)) {
this.child.stdout.removeListener('data', this.child.readyFunc);
callback();
}
};
this.child.stdout.on('data',this.child.readyFunc);
}
};
class OSRMmmapLoader extends OSRMBaseLoader {
constructor (scope) {
super(scope);
}
load (inputFile, callback) {
this.inputFile = inputFile;
this.shutdown(() => {
this.launch(callback);
});
}
osrmUp (callback) {
if (this.osrmIsRunning()) return callback(new Error("osrm-routed already running!"));
const command_arguments = util.format('%s -p %d -i %s -a %s --mmap', this.inputFile, this.scope.OSRM_PORT, this.scope.OSRM_IP, this.scope.ROUTING_ALGORITHM);
this.child = this.scope.runBin('osrm-routed', command_arguments, this.scope.environment, (err) => {
if (err && err.signal !== 'SIGINT') {
this.child = null;
throw new Error(util.format('osrm-routed %s: %s', errorReason(err), err.cmd));
}
});
this.child.readyFunc = (data) => {
if (/running and waiting for requests/.test(data)) {
this.child.stdout.removeListener('data', this.child.readyFunc);
callback();
}
};
this.child.stdout.on('data',this.child.readyFunc);
} }
}; };
@ -135,22 +175,32 @@ class OSRMLoader {
this.scope = scope; this.scope = scope;
this.sharedLoader = new OSRMDatastoreLoader(this.scope); this.sharedLoader = new OSRMDatastoreLoader(this.scope);
this.directLoader = new OSRMDirectLoader(this.scope); this.directLoader = new OSRMDirectLoader(this.scope);
this.mmapLoader = new OSRMmmapLoader(this.scope);
this.method = scope.DEFAULT_LOAD_METHOD; this.method = scope.DEFAULT_LOAD_METHOD;
} }
load (inputFile, callback) { load (inputFile, callback) {
if (!this.loader) {
this.loader = {shutdown: (cb) => cb() };
}
if (this.method === 'datastore') { if (this.method === 'datastore') {
this.directLoader.shutdown((err) => { this.loader.shutdown((err) => {
if (err) return callback(err); if (err) return callback(err);
this.loader = this.sharedLoader; this.loader = this.sharedLoader;
this.sharedLoader.load(inputFile, callback); this.sharedLoader.load(inputFile, callback);
}); });
} else if (this.method === 'directly') { } else if (this.method === 'directly') {
this.sharedLoader.shutdown((err) => { this.loader.shutdown((err) => {
if (err) return callback(err); if (err) return callback(err);
this.loader = this.directLoader; this.loader = this.directLoader;
this.directLoader.load(inputFile, callback); this.directLoader.load(inputFile, callback);
}); });
} else if (this.method === 'mmap') {
this.loader.shutdown((err) => {
if (err) return callback(err);
this.loader = this.mmapLoader;
this.mmapLoader.load(inputFile, callback);
});
} else { } else {
callback(new Error('*** Unknown load method ' + method)); callback(new Error('*** Unknown load method ' + method));
} }

View File

@ -32,7 +32,7 @@ module.exports = function () {
this.DEFAULT_ENVIRONMENT = Object.assign({STXXLCFG: stxxl_config}, process.env); this.DEFAULT_ENVIRONMENT = Object.assign({STXXLCFG: stxxl_config}, process.env);
this.DEFAULT_PROFILE = 'bicycle'; this.DEFAULT_PROFILE = 'bicycle';
this.DEFAULT_INPUT_FORMAT = 'osm'; this.DEFAULT_INPUT_FORMAT = 'osm';
this.DEFAULT_LOAD_METHOD = 'datastore'; this.DEFAULT_LOAD_METHOD = process.argv[process.argv.indexOf('-m') +1].match('mmap') ? 'mmap' : 'datastore';
this.DEFAULT_ORIGIN = [1,1]; this.DEFAULT_ORIGIN = [1,1];
this.OSM_USER = 'osrm'; this.OSM_USER = 'osrm';
this.OSM_UID = 1; this.OSM_UID = 1;

View File

@ -63,12 +63,16 @@ template <typename Algorithm> class Engine final : public EngineInterface
<< "\" with algorithm " << routing_algorithms::name<Algorithm>(); << "\" with algorithm " << routing_algorithms::name<Algorithm>();
facade_provider = std::make_unique<WatchingProvider<Algorithm>>(config.dataset_name); facade_provider = std::make_unique<WatchingProvider<Algorithm>>(config.dataset_name);
} }
else if (!config.memory_file.empty()) else if (!config.memory_file.empty() || config.use_mmap)
{ {
util::Log(logDEBUG) << "Using memory mapped filed at " << config.memory_file if (!config.memory_file.empty())
<< " with algorithm " << routing_algorithms::name<Algorithm>(); {
facade_provider = std::make_unique<ExternalProvider<Algorithm>>(config.storage_config, util::Log(logWARNING)
config.memory_file); << "The 'memory_file' option is DEPRECATED - using direct mmaping instead";
}
util::Log(logDEBUG) << "Using direct memory mapping with algorithm "
<< routing_algorithms::name<Algorithm>();
facade_provider = std::make_unique<ExternalProvider<Algorithm>>(config.storage_config);
} }
else else
{ {

View File

@ -89,6 +89,7 @@ struct EngineConfig final
int max_alternatives = 3; // set an arbitrary upper bound; can be adjusted by user int max_alternatives = 3; // set an arbitrary upper bound; can be adjusted by user
bool use_shared_memory = true; bool use_shared_memory = true;
boost::filesystem::path memory_file; boost::filesystem::path memory_file;
bool use_mmap = true;
Algorithm algorithm = Algorithm::CH; Algorithm algorithm = Algorithm::CH;
std::string verbosity; std::string verbosity;
std::string dataset_name; std::string dataset_name;

View File

@ -142,6 +142,10 @@ inline engine_config_ptr argumentsToEngineConfig(const Nan::FunctionCallbackInfo
if (shared_memory.IsEmpty()) if (shared_memory.IsEmpty())
return engine_config_ptr(); return engine_config_ptr();
auto mmap_memory = params->Get(Nan::New("mmap_memory").ToLocalChecked());
if (mmap_memory.IsEmpty())
return engine_config_ptr();
if (!memory_file->IsUndefined()) if (!memory_file->IsUndefined())
{ {
if (path->IsUndefined()) if (path->IsUndefined())
@ -190,6 +194,18 @@ inline engine_config_ptr argumentsToEngineConfig(const Nan::FunctionCallbackInfo
return engine_config_ptr(); return engine_config_ptr();
} }
} }
if (!mmap_memory->IsUndefined())
{
if (mmap_memory->IsBoolean())
{
engine_config->use_mmap = Nan::To<bool>(mmap_memory).FromJust();
}
else
{
Nan::ThrowError("mmap_memory option must be a boolean");
return engine_config_ptr();
}
}
if (path->IsUndefined() && !engine_config->use_shared_memory) if (path->IsUndefined() && !engine_config->use_shared_memory)
{ {

View File

@ -18,7 +18,7 @@
}, },
"scripts": { "scripts": {
"lint": "node ./node_modules/eslint/bin/eslint.js -c ./.eslintrc features/step_definitions/ features/support/", "lint": "node ./node_modules/eslint/bin/eslint.js -c ./.eslintrc features/step_definitions/ features/support/",
"test": "npm run lint && node ./node_modules/cucumber/bin/cucumber.js features/ -p verify && node ./node_modules/cucumber/bin/cucumber.js features/ -p mld", "test": "npm run lint && node ./node_modules/cucumber/bin/cucumber.js features/ -p verify && node ./node_modules/cucumber/bin/cucumber.js features/ -p verify -m mmap && node ./node_modules/cucumber/bin/cucumber.js features/ -p mld && node ./node_modules/cucumber/bin/cucumber.js features/ -p mld -m mmap",
"clean": "rm -rf test/cache", "clean": "rm -rf test/cache",
"docs": "./scripts/build_api_docs.sh", "docs": "./scripts/build_api_docs.sh",
"install": "node-pre-gyp install --fallback-to-build=false || ./scripts/node_install.sh", "install": "node-pre-gyp install --fallback-to-build=false || ./scripts/node_install.sh",

View File

@ -23,7 +23,9 @@ bool EngineConfig::IsValid() const
unlimited_or_more_than(max_results_nearest, 0) && unlimited_or_more_than(max_results_nearest, 0) &&
max_alternatives >= 0; max_alternatives >= 0;
return ((use_shared_memory && all_path_are_empty) || storage_config.IsValid()) && limits_valid; return ((use_shared_memory && all_path_are_empty) || (use_mmap && storage_config.IsValid()) ||
storage_config.IsValid()) &&
limits_valid;
} }
} }
} }

View File

@ -119,7 +119,10 @@ inline unsigned generateServerProgramOptions(const int argc,
"Load data from shared memory") // "Load data from shared memory") //
("memory_file", ("memory_file",
value<boost::filesystem::path>(&config.memory_file), value<boost::filesystem::path>(&config.memory_file),
"Store data in a memory mapped file rather than in process memory.") // "DEPRECATED: Will behave the same as --mmap.")(
"mmap,m",
value<bool>(&config.use_mmap)->implicit_value(true)->default_value(false),
"Map datafiles directly, do not use any additional memory.") //
("dataset-name", ("dataset-name",
value<std::string>(&config.dataset_name), value<std::string>(&config.dataset_name),
"Name of the shared memory dataset to connect to.") // "Name of the shared memory dataset to connect to.") //