perfetto-ui: Trace with large start ts has out-of-memory crash

Previously for grid lines, we were adding up start ts and step. If start
ts is very large and step is very little (i.e. when trace has only heap
profiles), end condition would never be reached because of the floating
point calculations.

Test trace: ?s=5524a7dc18f6f82a1adf33a3c36335f55f23dd8c9db9dbf7c587db99c904d91

Change-Id: Ice8ea6ced91852e0ce161250d78a6171af11eb8d
diff --git a/ui/src/frontend/gridline_helper.ts b/ui/src/frontend/gridline_helper.ts
index 9f9ac9b..b7a3c5a 100644
--- a/ui/src/frontend/gridline_helper.ts
+++ b/ui/src/frontend/gridline_helper.ts
@@ -72,12 +72,20 @@
   const step = getGridStepSize(span.duration, desiredSteps);
   const start = Math.round(span.start / step) * step;
   const lines: Array<[number, number]> = [];
-  for (let s = start; s < span.end; s += step) {
+  let previousTimestamp = Number.NEGATIVE_INFINITY;
+  // Iterating over the number of steps instead of
+  // for (let s = start; s < span.end; s += step) because if start is very large
+  // number and step very small, s will never reach end.
+  for (let i = 0; i < desiredSteps; i++) {
     let xPos = TRACK_SHELL_WIDTH;
-    xPos += Math.floor(timescale.timeToPx(s));
+    const timestamp = start + i * step;
+    xPos += Math.floor(timescale.timeToPx(timestamp));
     if (xPos < TRACK_SHELL_WIDTH) continue;
     if (xPos > width) break;
-    lines.push([xPos, s]);
+    if (Math.abs(timestamp - previousTimestamp) > Number.EPSILON) {
+      previousTimestamp = timestamp;
+      lines.push([xPos, timestamp]);
+    }
   }
   return lines;
 }