Select to view content in your preferred language

ArcGIS Server 11.1: Poor performance with Solve Vehicle Routing Problem

704
4
05-10-2023 08:05 AM
NicolasGIS
Frequent Contributor

Hello,

 

Since we upgraded from ArcGIS Enterprise 11.0 to  ArcGIS Enterprise 11.1, a simple geoprocessing service went from 3 min to run to 18 min.

With the same data and the following GP published:

import datetime
import os
import arcpy

# Scripts inputs (network, orders, depots, routes)
sample_gdb_path = r'C:\PATHTO\BUG_DATA.gdb'
in_network_dataset = os.path.join(sample_gdb_path, 'GRAPHE_ROUTIER\GRA_GRAPHE_G')
in_orders = os.path.join(sample_gdb_path, 'in_orders')
in_depots = os.path.join(sample_gdb_path, 'in_depots')
in_routes = os.path.join(sample_gdb_path, 'in_routes')

# Utility function to display tool execution progress
def time_now(message):
    return arcpy.AddMessage(message + datetime.datetime.now().strftime('%H:%M:%S'))
    
def solve_vehicule_routing_problem(scratchGDB, in_orders, in_depots, in_routes):
    # Network Analyst - Solve Vehicule Routing Problem
    # https://pro.arcgis.com/en/pro-app/latest/arcpy/network-analyst/migratingfrom10xarcpynetworkanalyst.htm
    time_now('Making VehicleRoutingProblemAnalysis layer...')
    #Create a new closest facility analysis layer.
    result_object = arcpy.na.MakeVehicleRoutingProblemAnalysisLayer(
        in_network_dataset, 
        "Vehicle Routing Problem", 
        "Guard", 
        "Minutes", 
        "Kilometers", 
        None, 
        "LOCAL_TIME_AT_LOCATIONS", 
        "ALONG_NETWORK", 
        "Medium", 
        "Medium", 
        "DIRECTIONS", 
        "CLUSTER", 
        "HALT"
    )
    #Get the layer object from the result object. The closest facility layer can
    #now be referenced using the layer object.
    layer_object = result_object.getOutput(0)
    #Get the names of all the sublayers within the closest facility layer.
    # https://pro.arcgis.com/en/pro-app/latest/arcpy/network-analyst/getnaclassnames.htm
    sublayer_names = arcpy.na.GetNAClassNames(layer_object)
    orders_layer = sublayer_names["Orders"]
    depots_layer = sublayer_names["Depots"]
    routes_layer = sublayer_names["Routes"]
    time_now('Adding orders locations...')
    arcpy.na.AddLocations(
        layer_object, 
        orders_layer, 
        in_orders, 
        "Name NO_OUVRAGE #;Description # #;ServiceTime ServiceTime #;TimeWindowStart # #;TimeWindowEnd # #;MaxViolationTime # #;TimeWindowStart2 # #;TimeWindowEnd2 # #;MaxViolationTime2 # #;InboundArriveTime # #;OutboundDepartTime # #;DeliveryQuantity_1 # #;DeliveryQuantity_2 # #;DeliveryQuantity_3 # #;DeliveryQuantity_4 # #;DeliveryQuantity_5 # #;DeliveryQuantity_6 # #;DeliveryQuantity_7 # #;DeliveryQuantity_8 # #;DeliveryQuantity_9 # #;PickupQuantity_1 # #;PickupQuantity_2 # #;PickupQuantity_3 # #;PickupQuantity_4 # #;PickupQuantity_5 # #;PickupQuantity_6 # #;PickupQuantity_7 # #;PickupQuantity_8 # #;PickupQuantity_9 # #;Revenue Revenue #;AssignmentRule # 3;RouteName # #;Sequence # #;CurbApproach # 0", 
        "5000 Meters", 
    )
    time_now('Adding depots locations...')
    arcpy.na.AddLocations(
        layer_object, 
        depots_layer, 
        in_depots, 
        "Name Name #;Description Description #;TimeWindowStart TimeWindowStart1 #;TimeWindowEnd TimeWindowEnd1 #;TimeWindowStart2 TimeWindowStart2 #;TimeWindowEnd2 TimeWindowEnd2 #;CurbApproach CurbApproach 0", 
        "5000 Meters"
    )
    time_now('Adding routes locations...')
    arcpy.na.AddLocations(
        layer_object, 
        routes_layer, 
        in_routes, 
        "Name Name #;Description Description #;StartDepotName StartDepotName #;EndDepotName EndDepotName #;StartDepotServiceTime StartDepotServiceTime #;EndDepotServiceTime EndDepotServiceTime #;EarliestStartTime EarliestStartTime '8:00:00 AM';LatestStartTime LatestStartTime '10:00:00 AM';ArriveDepartDelay ArriveDepartDelay #;Capacity_1 # #;Capacity_2 # #;Capacity_3 # #;Capacity_4 # #;Capacity_5 # #;Capacity_6 # #;Capacity_7 # #;Capacity_8 # #;Capacity_9 # #;FixedCost FixedCost #;CostPerUnitTime CostPerUnitTime 1;CostPerUnitDistance CostPerUnitDistance #;OvertimeStartTime OvertimeStartTime #;CostPerUnitOvertime CostPerUnitOvertime #;MaxOrderCount MaxOrderCount 30;MaxTotalTime MaxTotalTime #;MaxTotalTravelTime MaxTotalTravelTime #;MaxTotalDistance MaxTotalDistance #;AssignmentRule AssignmentRule 1;Shape_Length Shape_Length #", 
        "5000 Meters"
    )
    time_now('Solving Vehicule Routing Problem ...')
    # https://pro.arcgis.com/en/pro-app/latest/tool-reference/network-analyst/solve.htm
    arcpy.na.Solve(
        layer_object, 
        "HALT", 
        "TERMINATE", 
        None, ''
    )
    time_now('Generating directions ...')
    # https://pro.arcgis.com/en/pro-app/latest/arcpy/network-analyst/generatedirectionsfeatures.htm
    arcpy.na.GenerateDirectionsFeatures(layer_object, os.path.join(scratchGDB, 'Directions'))
    
    time_now('Copying routes and stops ...')
    arcpy.management.CopyFeatures(routes_layer, os.path.join(scratchGDB, 'Routes'))
    arcpy.management.CopyFeatures(orders_layer, os.path.join(scratchGDB, 'Orders'))
    
if __name__ == "__main__":
    scratchGDB = arcpy.env.scratchGDB
    solve_vehicule_routing_problem(scratchGDB, in_orders, in_depots, in_routes)

 

 

On 11.0:

NicolasGIS_0-1683731001004.png

 

On 11.1:

NicolasGIS_1-1683731033984.png

 

5 times slower. Seems like a performance regression to me.

Anybody noticing the same phenomena ?

 

Thanks

 

 

0 Kudos
4 Replies
GoranGobac
Occasional Contributor

Hi @NicolasGIS ,
I would say it is a feature not a problem. hahaha
But joke a said it can happen that your published script is additionale manipulated from ArcGIS Server.
What we learned and do with custom scripts is after they are published we overwrite the script in ArcGIS Server Directory with the one from your ArcGIS Pro directory.
why? Because by publishing ArcGIS Server is manipulating your script with Environmental Variables. 
This you could try if you did not already.
Br
Goran

0 Kudos
NicolasGIS
Frequent Contributor

Hi @GoranGobac ,

Thanks for your reply. As you can see in my example, the GP has been simplified to bare minimum in order to work on this issue with support.

Having a look at the modified Python script, not much changed so I don't think that it is the issue. 

I do think there has been a regression in the routing engine as it's taking ages as well in latest ArcGIS Pro versions which was not the case before. But my main concern currently is the ArcGIS Server as users are not really pleased having to wait 30 min to get the results of the 'SolveRoutingProblem' ! I had to increase the timeout of the GP in ArcGIS Server manager to 45 min as once it took 31 min !

Support logged the following:

BUG-000158801: Poor performance when running a GPServer Tool solving Vehicle Routing Problem.

Let's hope it's gonna be fixed.

0 Kudos
Felipe
by
New Contributor

Hi @NicolasGIS and @GoranGobac ,

 

I know that this topic is a bit old, but did you solve this issue regarding the performance of a customized Python Toolbox?

I have similar case: a geoprocessing service which was running in 9 minutes on ArcGIS Server 11.1 hosted on Windows 2019 went to 4 hours. After upgrading to 11.3 the performance improved to 15 minutes, but I had to increase the timeout.

Thank you!

0 Kudos
NicolasGIS
Frequent Contributor

Hi @Felipe,

no official news on ESRI side regarding the BUG but in the meantime I upgraded to 11.3 just like you and it went back to 3 minutes without changing a single line of code.