Perf

JavaScript performance comparison

Test case created by

Preparation code


      
      <script>
Benchmark.prototype.setup = function() {
  const modalities = 2;
  const roadSegmentIDs = 60;
  const intensities = 24 * 7;
  
  var seed = 1;
  function random() {
    var x = Math.sin(seed++) * 10000;
    return x - Math.floor(x);
  }
  
  // from: https://stackoverflow.com/questions/6122571/simple-non-secure-hash-function-for-javascript
  // Very simple (and fast) hashing function
  function calcHash(hashableStr) {
    var hash = 0;
    if (hashableStr.length == 0) {
      return hash;
    }
    for (var i = 0; i < hashableStr.length; i++) {
      var char = hashableStr.charCodeAt(i);
      hash = (hash << 5) - hash + char;
      hash = hash & hash; // Convert to 32bit integer
    }
    return hash;
  }
  
  
  function calcIntensityUID(modality, timeFrom, segmentId) {
    return `${modality}+${segmentId}+${timeFrom}`;
  }
  let intensitiesMap = new Map();
  
  const timeStep = 60 * 60 * 1000;
  let trafficModalitiesObserved = new Map();
  for (let i = 0; i < modalities; i++) {
    for (let j = 0; j < roadSegmentIDs; j++) {
      for (let k = 0; k < intensities; k++) {
        const modality = i.toString();
        const roadSegmentID = j;
        const intensity = random();
        const from = 1587732335 + k * timeStep;
        const to = 1587732335 + k * timeStep + timeStep;
  
        const tfMsgByRoadSegment =
          trafficModalitiesObserved.get(modality) || new Map();
        const tfMsgByDateObserved =
          tfMsgByRoadSegment.get(roadSegmentID) || new Map();
  
        tfMsgByDateObserved.set(from, { from, to, intensity });
        tfMsgByRoadSegment.set(roadSegmentID, tfMsgByDateObserved);
        trafficModalitiesObserved.set(modality, tfMsgByRoadSegment);
  
        const uid = calcIntensityUID(modality, from, roadSegmentID);
        intensitiesMap.set(uid, intensity);
      }
    }
  }
  
  const roadSegments = new Map();
  for (let i = 0; i < roadSegmentIDs; i++) {
    roadSegments.set(i, { linestring: "test" });
  }
  
  const startTimestampUnixMs = 1587732335;
  const endTimeStampUnixMs = 1987732335;
  
  const modality = "0"
  
  function generateAllUIDsForRequest(
  modality,
  startTimeStamp,
  endTimeStamp,
  segmentId
  ) {
  let currentMoment = startTimeStamp;
  const endMoment = endTimeStamp;
  const increase = 3600000;
  const result = [];
  while (currentMoment < endMoment) {
      const uid = calcIntensityUID(modality, currentMoment, segmentId);
      if (!intensitiesMap.has(uid)) {
  
        currentMoment=endMoment;
   
      } else {
        result.push(intensitiesMap.get(uid));
      }
      currentMoment += increase;
    }
  return result;
  }

};
</script>

Test runner

Warning! For accurate results, please disable Firebug before running the tests. (Why?)

Java applet disabled.

Testing in CCBot 2.0.0 / Other 0.0.0
Test Ops/sec
Original
// Get all city flow messages by modality
  const cfDataByRoadSegmentId = Array.from(trafficModalitiesObserved.get(modality))
    // Filter to only take flow messages that have a known geometry segment
    .filter(val => roadSegments.has(val[0]))
    // Drop the map inside so `Map<number, Map<number, TrafficModalitiesObservedUnixMs>>` becomes `Map<number, TrafficModalitiesObservedUnixMs>` with the remaining key being the roadSegmentId
    .map(val => [val[0], Array.from(val[1].values())])
    // Filter out all messages that fall outside the api call timerange
    .map(
      val => [
          val[0],
          val[1].filter(val => val.from >= startTimestampUnixMs && val.to <= endTimeStampUnixMs)
        ]
    )
    // Filter out roadsegments that no longer have any city flow data because of the time range
    .filter(val => val[1].length > 0);

  const segmentIds = cfDataByRoadSegmentId.map(val => val[0]);
  const intensities = cfDataByRoadSegmentId.map(val => val[1].map(val => val.intensity));
  const geometries = segmentIds.map(id => roadSegments.get(id));

const result = {intensities: intensities, segmentIDs: segmentIds, geometries: geometries}
pending…
For Loop
const result = { geometries: [], segmentIds: [], intensities: [] };

// Get all city flow messages by modality
const cfByDateAndRoadSegmentID = Array.from(trafficModalitiesObserved.get(modality));

for (let i = 0; i < cfByDateAndRoadSegmentID.length; i++) {
  let roadSegmentHasFlowMsg = false;
  const [roadSegment, cfByDateObserved] = cfByDateAndRoadSegmentID[i];

  // Filter to only take flow messages that have a known geometry segment
  if (roadSegments.has(roadSegment)) {
    const cfs = Array.from(cfByDateObserved.values());
    const intensitiesOfSingleRoadSegment = [];
    for (let j = 0; j < cfs.length; j++) {
      // Filter out all messages that fall outside the api call timerange
      // When a cityflows message is found that is after the end timestamp we can assume all the remaining data will be out of range (data is expected to be sorted)
      if (cfs[j].to > endTimeStampUnixMs) break;

      if (cfs[j].from >= startTimestampUnixMs) {
        intensitiesOfSingleRoadSegment.push(cfs[j].intensity);
        roadSegmentHasFlowMsg = true;
      }
    }
    if (roadSegmentHasFlowMsg) {
      result.intensities.push(intensitiesOfSingleRoadSegment);
      result.segmentIds.push(roadSegment.toString());
      result.geometries.push(roadSegments.get(roadSegment));
    }
  }
}
pending…
Hashing
const result = { geometries: [], segmentIds: [], intensities: [] };

// iterate over map with key and value
for (let [segmentId, geometry] of roadSegments) {
  const intensities = generateAllUIDsForRequest(modality, startTimestampUnixMs, endTimeStampUnixMs, segmentId);
    result.geometries.push(geometry);
    result.segmentIds.push(segmentId);
    result.intensities.push(intensities);
}
pending…
For Loop 2
const result = { geometries: [], segmentIds: [], intensities: [] };

// Get all city flow messages by modality
const cfByDateAndRoadSegmentID = trafficModalitiesObserved.get(modality);

for (const [roadSegment, cfByDateObserved] of cfByDateAndRoadSegmentID) {
  let roadSegmentHasFlowMsg = false;
  //const [roadSegment, cfByDateObserved] = cfByDateAndRoadSegmentID[i];

  // Filter to only take flow messages that have a known geometry segment
  if (roadSegments.has(roadSegment)) {
    const cfs = Array.from(cfByDateObserved.values());
    const intensitiesOfSingleRoadSegment = [];
    for (let j = 0; j < cfs.length; j++) {
      // Filter out all messages that fall outside the api call timerange
      // When a cityflows message is found that is after the end timestamp we can assume all the remaining data will be out of range (data is expected to be sorted)
      if (cfs[j].to > endTimeStampUnixMs) break;

      if (cfs[j].from >= startTimestampUnixMs) {
        intensitiesOfSingleRoadSegment.push(cfs[j].intensity);
        roadSegmentHasFlowMsg = true;
      }
    }
    if (roadSegmentHasFlowMsg) {
      result.intensities.push(intensitiesOfSingleRoadSegment);
      result.segmentIds.push(roadSegment.toString());
      result.geometries.push(roadSegments.get(roadSegment));
    }
  }
}
pending…

You can edit these tests or add even more tests to this page by appending /edit to the URL.

0 Comments