docs: void start(CmdArgs args) {
          String graphLocation = args.get("graph.location", "");
          String propLocation = args.get("measurement.location", "");
          boolean cleanGraph = args.getBool("measurement.clean", false);
          String summaryLocation = args.get("measurement.summaryfile", "");
          String timeStamp = new SimpleDateFormat("yyyy-MM-dd_HH_mm_ss").format(new Date());
          put("measurement.timestamp", timeStamp);
          if (isEmpty(propLocation)) {
              propLocation = "measurement" + timeStamp + ".properties";
          }
  
          seed = args.getLong("measurement.seed", 123);
          put("measurement.gitinfo", args.get("measurement.gitinfo", ""));
          int count = args.getInt("measurement.count", 5000);
  
          GraphHopper hopper = new GraphHopperOSM() {
              @Override
              protected void prepareCH() {
                  StopWatch sw = new StopWatch().start();
                  super.prepareCH();
                  // note that we measure the total time of all (possibly edge&node) CH preparations
                  put(Parameters.CH.PREPARE + "time", sw.stop().getMillis());
                  int edges = getGraphHopperStorage().getEdges();
                  if (!getCHFactoryDecorator().getNodeBasedWeightings().isEmpty()) {
                      Weighting weighting = getCHFactoryDecorator().getNodeBasedWeightings().get(0);
                      int edgesAndShortcuts = getGraphHopperStorage().getGraph(CHGraph.class, weighting).getEdges();
                      put(Parameters.CH.PREPARE + "node.shortcuts", edgesAndShortcuts - edges);
                  }
                  if (!getCHFactoryDecorator().getEdgeBasedWeightings().isEmpty()) {
                      Weighting weighting = getCHFactoryDecorator().getEdgeBasedWeightings().get(0);
                      int edgesAndShortcuts = getGraphHopperStorage().getGraph(CHGraph.class, weighting).getEdges();
                      put(Parameters.CH.PREPARE + "edge.shortcuts", edgesAndShortcuts - edges);
                  }
              }
  
              @Override
              protected void loadOrPrepareLM() {
                  StopWatch sw = new StopWatch().start();
                  super.loadOrPrepareLM();
                  put(Landmark.PREPARE + "time", sw.stop().getMillis());
              }
  
              @Override
              protected DataReader importData() throws IOException {
                  StopWatch sw = new StopWatch().start();
                  DataReader dr = super.importData();
                  put("graph.import_time", sw.stop().getSeconds());
                  return dr;
              }
          };
  
          hopper.init(args).
                  forDesktop();
          if (cleanGraph) {
              hopper.clean();
          }
  
          hopper.getCHFactoryDecorator().setDisablingAllowed(true);
          hopper.getLMFactoryDecorator().setDisablingAllowed(true);
          hopper.importOrLoad();
  
          GraphHopperStorage g = hopper.getGraphHopperStorage();
          EncodingManager encodingManager = hopper.getEncodingManager();
          if (encodingManager.fetchEdgeEncoders().size() != 1) {
              throw new IllegalArgumentException("There has to be exactly one encoder for each measurement");
          }
          FlagEncoder encoder = encodingManager.fetchEdgeEncoders().get(0);
          String vehicleStr = encoder.toString();
  
          StopWatch sw = new StopWatch().start();
          try {
              maxNode = g.getNodes();
              boolean isCH = false;
              boolean isLM = false;
              GHBitSet allowedEdges = printGraphDetails(g, vehicleStr);
              printMiscUnitPerfTests(g, isCH, encoder, count * 100, allowedEdges);
              printLocationIndexQuery(g, hopper.getLocationIndex(), count);
              printTimeOfRouteQuery(hopper, isCH, isLM, count / 20, "routing", vehicleStr, true, -1, true, false);
  
              if (hopper.getLMFactoryDecorator().isEnabled()) {
                  System.gc();
                  isLM = true;
                  int activeLMCount = 12;
                  for (; activeLMCount > 3; activeLMCount -= 4) {
                      printTimeOfRouteQuery(hopper, isCH, isLM, count / 4, "routingLM" + activeLMCount, vehicleStr, true, activeLMCount, true, false);
                  }
  
                  // compareRouting(hopper, vehicleStr, count / 5);
              }
  
              if (hopper.getCHFactoryDecorator().isEnabled()) {
                  isCH = true;
  //                compareCHWithAndWithoutSOD(hopper, vehicleStr, count/5);
                  if (hopper.getLMFactoryDecorator().isEnabled()) {
                      isLM = true;
                      System.gc();
                      // try just one constellation, often ~4-6 is best
                      int lmCount = 5;
                      printTimeOfRouteQuery(hopper, isCH, isLM, count, "routingCHLM" + lmCount, vehicleStr, true, lmCount, true, false);
                  }
  
                  isLM = false;
                  System.gc();
                  if (!hopper.getCHFactoryDecorator().getNodeBasedWeightings().isEmpty()) {
                      Weighting weighting = hopper.getCHFactoryDecorator().getNodeBasedWeightings().get(0);
                      CHGraph lg = g.getGraph(CHGraph.class, weighting);
                      fillAllowedEdges(lg.getAllEdges(), allowedEdges);
                      printMiscUnitPerfTests(lg, isCH, encoder, count * 100, allowedEdges);
                      printTimeOfRouteQuery(hopper, isCH, isLM, count, "routingCH", vehicleStr, true, -1, true, false);
                      printTimeOfRouteQuery(hopper, isCH, isLM, count, "routingCH_no_sod", vehicleStr, true, -1, false, false);
                      printTimeOfRouteQuery(hopper, isCH, isLM, count, "routingCH_no_instr", vehicleStr, false, -1, true, false);
                  }
                  if (!hopper.getCHFactoryDecorator().getEdgeBasedWeightings().isEmpty()) {
                      printTimeOfRouteQuery(hopper, isCH, isLM, count, "routingCH_edge", vehicleStr, true, -1, false, true);
                      printTimeOfRouteQuery(hopper, isCH, isLM, count, "routingCH_edge_no_instr", vehicleStr, false, -1, false, true);
                  }
              }
          } catch (Exception ex) {
              logger.error("Problem while measuring " + graphLocation, ex);
              put("error", ex.toString());
          } finally {
              put("gh.gitinfo", Constants.GIT_INFO);
              put("measurement.count", count);
              put("measurement.seed", seed);
              put("measurement.time", sw.stop().getMillis());
              System.gc();
              put("measurement.totalMB", getTotalMB());
              put("measurement.usedMB", getUsedMB());
  
              if (!summaryLocation.trim().isEmpty()) {
                  writeSummary(summaryLocation, propLocation);
              }
              storeProperties(graphLocation, propLocation);
          }
      }