Osrm-backend: c++ slower then php?

Created on 10 May 2016  路  10Comments  路  Source: Project-OSRM/osrm-backend

The test
8 diferents points and making a route using all
using a for loop to repeat the process 5000 times
The osrm file is from my region(i get my country osm and use the osmconvert with a bounding box of my region), all the files have 11 MB

The php code runs in the same machine of osrm-routed to avoid network problems
The c++ code is a variation of the code in example folder

VM
Virtualbox
4x 2.0 ghz
4 Gb ram
10 Gb disk(the host disk are a 500 Gb 7200rpm)

VPS
4x2.3 Ghz
1 Gb ram
10 Gb disk(high speed read and write, probably some raid 0 configuration)

Results
Virtualbox
C++ near of 5/6 minutes
php near of 3/4 minutes

VPS
C++ 1m49.512s
PHP 1m0.938s

Codes

<?php
$lat[0] = "-22.121093"; 
$long[0] = "-51.404997";

$lat[1]     = "-22.140927";
$long[1]    = "-51.400867";

$lat[2]     = "-22.134668";
$long[2]    = "-51.362715";

$lat[3]     = "-22.153748";
$long[3]    = "-51.370611";

$lat[4]     = "-22.153589";
$long[4]    = "-51.391039";

$lat[5]     = "-22.153748";
$long[5]    = "-51.412840";

$lat[6]     = "-22.154225";
$long[6]    = "-51.415071";

$lat[7]     = "-22.123748";
$long[7]    = "-51.212840"; 

//$lat[8]       = "-22.146682";
//$long[8]  = "-51.312715";

for($i=0;i<5000;i++){
   $jsonurl = "http://127.0.0.1:5000/route/v1/driving/$long[0],$lat[0];$long[1],$lat[1];$long[2],$lat[2];$long[3],$lat[3];$long[4],$lat[4];$long[5],$lat[5];$long[6],$lat[6];$long[7],$lat[7]";
$json = file_get_contents($jsonurl);
$array = json_decode($json,true);
}
echo "End"


#include "osrm/route_parameters.hpp"
#include "osrm/table_parameters.hpp"
#include "osrm/nearest_parameters.hpp"
#include "osrm/trip_parameters.hpp"
#include "osrm/match_parameters.hpp"

#include "osrm/coordinate.hpp"
#include "osrm/engine_config.hpp"
#include "osrm/json_container.hpp"

#include "osrm/status.hpp"
#include "osrm/osrm.hpp"

#include <string>
#include <utility>
#include <iostream>
#include <exception>

#include <cstdlib>

int main(int argc, const char *argv[]) try
{
    int i;

    if (argc < 2)
    {
        std::cerr << "Usage: " << argv[0] << " data.osrm\n";
        return EXIT_FAILURE;
    }

    using namespace osrm;

    // Configure based on a .osrm base path, and no datasets in shared mem from osrm-datastore
   EngineConfig config;
    config.storage_config = {argv[1]};
    config.use_shared_memory = false;


    // Routing machine with several services (such as Route, Table, Nearest, Trip, Match)
    OSRM osrm{config};

    // The following shows how to use the Route service; configure this service
    RouteParameters params;

    // Route in monaco
    //0
    params.coordinates.push_back({util::FloatLongitude(-51.404997), util::FloatLatitude(-22.121093)});
//1
    params.coordinates.push_back({util::FloatLongitude(-51.400867), util::FloatLatitude(-22.140927)});
//2
    params.coordinates.push_back({util::FloatLongitude(-51.362715), util::FloatLatitude(-22.134668)});
//3
    params.coordinates.push_back({util::FloatLongitude(-51.370611), util::FloatLatitude(-22.153748)});
//4
    params.coordinates.push_back({util::FloatLongitude(-51.391039), util::FloatLatitude(-22.153589)});
//5
    params.coordinates.push_back({util::FloatLongitude(-51.412840), util::FloatLatitude(-22.153748)});
//6
    params.coordinates.push_back({util::FloatLongitude(-51.415071), util::FloatLatitude(-22.154225)});
//7
    params.coordinates.push_back({util::FloatLongitude(-51.212840), util::FloatLatitude(-22.153748)});

    // Response is in JSON format
    json::Object result;
    // Execute routing request, this does the heavy lifting
    for(i=0;i<5000;i++)
        const auto status = osrm.Route(params, result);

        std::cerr << "END\n";
}
catch (const std::exception &e)
{
    std::cerr << "Error: " << e.what() << std::endl;
    return EXIT_FAILURE;
}


All 10 comments

@gabrielozaki There is a startup time in the C++ version - the data file needs to be loaded into memory. 11MB is not a lot and should load fast (<1 second), but your measurements are not equal.

Additionally, what optimization flags did you compile your test code with? If osrm-routed is built with -O3 (the default for a Release build) and your C++ code is built with -O1, then you'll see a significant difference in performance.

Hi, i have use the O3 on compilation process
with default options :

date && time ./osrm-example.O0 /root/prudente/prudente.osrm && date
Tue May 10 23:48:48 EDT 2016
FIM

real    1m4.636s
user    1m1.410s
sys 0m2.761s
Tue May 10 23:49:53 EDT 2016

with -O3:

date && time ./osrm-example /root/prudente/prudente.osrm && date
Tue May 10 23:47:07 EDT 2016
FIM

real    0m36.413s
user    0m33.393s
sys 0m2.736s
Tue May 10 23:47:44 EDT 2016

PHP code

date && time php teste.php && date
Tue May 10 23:45:27 EDT 2016
real    1m1.304s
user    0m0.917s
sys 0m0.640s
Tue May 10 23:46:29 EDT 2016

Is possible get better results for this test?

Try

#include <chrono>

...

auto t0 = std::chrono::high_resolution_clock::now();

for (...)
    osrm.Route(...);

auto t1 = std::chrono::high_resolution_clock::now();

std::cout << std::chrono::duration_cast<std::chrono::milliseconds>(t1 - t0).count() << " ms\n";

and compile the example with

cmake .. -DCMAKE_BUILD_TYPE=Release

too.

@daniel-j-h Hi

The result

./osrm-example /root/prudente/prudente.osrm        
65892 ms

@gabrielozaki It doesn't look like you're doing any requests in parallel.

osrm-routed is multi-threaded, and the OSRM C++ interface is thread-safe, so you could update your code to run many queries in parallel and it would probably be quite a lot faster overall. Each request won't be quicker, but the total runtime should be faster.

You can do a quick test running requests explicitly in parallel:

#include <tbb/parallel_for.h>
#include <tbb/blocked_range.h>

...

using range = tbb::blocked_range<size_t>;
const constexpr auto batch = 500;

tbb::parallel_for(range{0, 5000, batch}, [&] (const range&) {
  json::Object o;  // you probably can optimize this by caching a thread local result object
  osrm.Route(params, o);
});

and then play with batch to set the min. number of requests per threads.

Using @daniel-j-h modifications and -O3 optimization flag i get this results

date && time ./osrm-example /root/prudente/prudente.osrm && date
Wed May 11 13:27:11 EDT 2016

real    0m0.773s
user    0m0.154s
sys 0m0.059s
Wed May 11 13:27:11 EDT 2016

This is a really amazing result, thanks @danpat and @daniel-j-h

@gabrielozaki You should check that you're getting a valid response - make sure there is no error code being returned.

While I expect 5000 routes should be a lot faster than you were getting, 700ms seems a little suspicious.

I'd expect roughly 5ms per request. With 4 cores and 5000 requests, that means it should take somewhere in the order of 5 seconds. 700ms seems a bit too fast.

Yep, checking the result object for error is probably a good idea. Could totally be the case that the optimizer removes all of the code as dead code, since we're not really using it any further.

Maybe accumulate all distances or something like that.

I think we are good to close here.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

AliKarami picture AliKarami  路  3Comments

koussaimb picture koussaimb  路  4Comments

ardanika picture ardanika  路  3Comments

stvno picture stvno  路  3Comments

freenerd picture freenerd  路  4Comments