diff mbox

[i-g-t,1/8] trace.pl: Improve time axis labels

Message ID 20180718094514.5903-2-tvrtko.ursulin@linux.intel.com (mailing list archive)
State New, archived
Headers show

Commit Message

Tvrtko Ursulin July 18, 2018, 9:45 a.m. UTC
From: Tvrtko Ursulin <tvrtko.ursulin@intel.com>

It is possible to customize the axis display so change it to display
timestamps in seconds on the major axis (with six decimal spaces) and
millisecond offsets on the minor axis.

v2:
 * Give up on broken relative timestamps.

v3:
 * Drop all date complications and just use micro seconds throughout.
   (John Harrison)

Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Suggested-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Cc: John Harrison <John.C.Harrison@Intel.com>
Reviewed-by: John Harrison <John.C.Harrison@Intel.com> # v2
---
 scripts/trace.pl | 72 ++++++++++++++++++++++++++++++++----------------
 1 file changed, 48 insertions(+), 24 deletions(-)

Comments

John Harrison July 18, 2018, 8:03 p.m. UTC | #1
On 7/18/2018 2:45 AM, Tvrtko Ursulin wrote:
> From: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
>
> It is possible to customize the axis display so change it to display
> timestamps in seconds on the major axis (with six decimal spaces) and
> millisecond offsets on the minor axis.
>
> v2:
>   * Give up on broken relative timestamps.
>
> v3:
>   * Drop all date complications and just use micro seconds throughout.
>     (John Harrison)
>
> Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
> Suggested-by: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: Chris Wilson <chris@chris-wilson.co.uk>
> Cc: John Harrison <John.C.Harrison@Intel.com>
> Reviewed-by: John Harrison <John.C.Harrison@Intel.com> # v2
> ---
>   scripts/trace.pl | 72 ++++++++++++++++++++++++++++++++----------------
>   1 file changed, 48 insertions(+), 24 deletions(-)
>
> diff --git a/scripts/trace.pl b/scripts/trace.pl
> index fc1713e4f9a7..3ad5effafd0a 100755
> --- a/scripts/trace.pl
> +++ b/scripts/trace.pl
> @@ -329,20 +329,6 @@ sub sanitize_ctx
>   	}
>   }
>   
> -sub ts
> -{
> -	my ($us) = @_;
> -	my ($y, $mo, $d, $h, $m, $s);
> -
> -	$s = int($us / 1000000);
> -	$us = $us % 1000000;
> -
> -	($s, $m, $h, $d, $mo, $y) = gmtime($s);
> -
> -	return sprintf('%04u-%02u-%02u %02u:%02u:%02u.%06u',
> -		        $y, 1 + $mo, $d, $h, $m, $s, int($us));
> -}
> -
>   # Main input loop - parse lines and build the internal representation of the
>   # trace using a hash of requests and some auxilliary data structures.
>   my $prev_freq = 0;
> @@ -912,7 +898,7 @@ foreach my $key (sort sortQueue keys %db) {
>   		$style = 'color: black; background-color: ' .
>   			 ctx_colour($ctx, 'queue');
>   		$content = "$name<br>$db{$key}->{'submit-delay'}us <small>($db{$key}->{'execute-delay'}us)</small>";
> -		$startend = 'start: \'' . ts($queue) . '\', end: \'' . ts($submit) . '\'';
> +		$startend = 'start: ' . $queue . ', end: ' . $submit;
>   		print "\t{id: $i, key: $skey, $type group: $group, subgroup: $subgroup, subgroupOrder: $subgroup, content: '$content', $startend, style: \'$style\'},\n";
>   		$i++;
>   	}
> @@ -923,7 +909,7 @@ foreach my $key (sort sortQueue keys %db) {
>   		$style = 'color: black; background-color: ' .
>   			 ctx_colour($ctx, 'ready');
>   		$content = "<small>$name<br>$db{$key}->{'execute-delay'}us</small>";
> -		$startend = 'start: \'' . ts($submit) . '\', end: \'' . ts($start) . '\'';
> +		$startend = 'start: ' . $submit . ', end: ' . $start;
>   		print "\t{id: $i, key: $skey, $type group: $group, subgroup: $subgroup, subgroupOrder: $subgroup, content: '$content', $startend, style: \'$style\'},\n";
>   		$i++;
>   	}
> @@ -942,7 +928,7 @@ foreach my $key (sort sortQueue keys %db) {
>   		$content .= ' <small><i>++</i></small> ' if exists $db{$key}->{'no-end'};
>   		$content .= ' <small><i>+</i></small> ' if exists $db{$key}->{'no-notify'};
>   		$content .= "<br>$db{$key}->{'duration'}us <small>($db{$key}->{'context-complete-delay'}us)</small>";
> -		$startend = 'start: \'' . ts($start) . '\', end: \'' . ts($notify) . '\'';
> +		$startend = 'start: ' . $start . ', end: ' . $notify;
>   		print "\t{id: $i, key: $skey, $type group: $group, subgroup: $subgroup, subgroupOrder: $subgroup, content: '$content', $startend, style: \'$style\'},\n";
>   		$i++;
>   	}
> @@ -956,7 +942,7 @@ foreach my $key (sort sortQueue keys %db) {
>   		$content .= ' <small><i>???</i></small> ' if exists $db{$key}->{'incomplete'};
>   		$content .= ' <small><i>++</i></small> ' if exists $db{$key}->{'no-end'};
>   		$content .= ' <small><i>+</i></small> ' if exists $db{$key}->{'no-notify'};
> -		$startend = 'start: \'' . ts($notify) . '\', end: \'' . ts($end) . '\'';
> +		$startend = 'start: ' . $notify . ', end: ' . $end;
>   		print "\t{id: $i, key: $skey, $type group: $group, subgroup: $subgroup, subgroupOrder: $subgroup, content: '$content', $startend, style: \'$style\'},\n";
>   		$i++;
>   	}
> @@ -974,7 +960,7 @@ foreach my $item (@freqs) {
>   
>   	$start = $first_ts if $start < $first_ts;
>   	$end = $last_ts if $end > $last_ts;
> -	$startend = 'start: \'' . ts($start) . '\', end: \'' . ts($end) . '\'';
> +	$startend = 'start: ' . $start . ', end: ' . $end;
>   	print "\t{id: $i, type: 'range', group: 0, content: '$freq', $startend},\n";
>   	$i++;
>   }
> @@ -988,18 +974,55 @@ if ($gpu_timeline) {
>   
>   		$start = $first_ts if $start < $first_ts;
>   		$end = $last_ts if $end > $last_ts;
> -		$startend = 'start: \'' . ts($start) . '\', end: \'' . ts($end) . '\'';
> +		$startend = 'start: ' . $start . ', end: ' . $end;
>   		print "\t{id: $i, type: 'range', group: 1, $startend},\n";
>   		$i++;
>   	}
>   }
>   
> -my $end_ts = ts($first_ts + $width_us);
> -$first_ts = ts($first_ts);
> +my $end_ts = $first_ts + $width_us;
> +$first_ts = $first_ts;
>   
>   print <<ENDHTML;
>     ]);
>   
> +  function majorAxis(date, scale, step) {
> +	var s = date / 1000000;
> +	var precision;
> +
> +	if (scale == 'millisecond')
> +		precision = 6;
> +	else if (scale == 'second')
> +		precision = 3;
> +	else
> +		precision = 0;
> +
> +	return s.toFixed(precision) + "s";
> +  }
> +
> +  function minorAxis(date, scale, step) {
> +	var t = date;
> +	var precision;
> +	var unit;
> +
> +	if (scale == 'millisecond') {
> +		t %= 1000;
> +		precision = 0;
> +		unit = 'us';
> +	} else if (scale == 'second') {
> +		t /= 1000;
> +		t %= 1000;
> +		precision = 0;
> +		unit = 'ms';
> +	} else {
> +		t /= 1000000;
> +		precision = 1;
> +		unit = 's';
> +	}
> +
> +	return t.toFixed(precision) + unit;
> +  }
> +
>     // Configuration for the Timeline
>     var options = { groupOrder: 'content',
>   		  horizontalScroll: true,
> @@ -1007,8 +1030,9 @@ print <<ENDHTML;
>   		  stackSubgroups: false,
>   		  zoomKey: 'ctrlKey',
>   		  orientation: 'top',
> -		  start: '$first_ts',
> -		  end: '$end_ts'};
> +		  format: { majorLabels: majorAxis, minorLabels: minorAxis },
> +		  start: $first_ts,
> +		  end: $end_ts};
>   
>     // Create a Timeline
>     var timeline = new vis.Timeline(container, items, groups, options);

Woohoo!

This one seems to work fine on both Firefox and Chrome. It even works on 
IE and Edge unlike the previous version! I guess they can only cope with 
raw times not dates!?

One thing I've just noticed is that there is also a 'now' line on the 
timeline - a red vertical bar across the entire timeline. On the old 
'date' versions, it was following the current system time and hence 
wandering forwards at one second per second. On this version, it is out 
of position and advancing at one millisecond per second. Presumably 
because you are scaling the axes by a factor of one thousand in order to 
gain the necessary precision in the plot. Something of a curiosity but 
certainly not a problem!

Ship it :)

Reviewed-by: John Harrison <John.C.Harrison@Intel.com>
Tvrtko Ursulin July 19, 2018, 9:39 a.m. UTC | #2
On 18/07/2018 21:03, John Harrison wrote:
> On 7/18/2018 2:45 AM, Tvrtko Ursulin wrote:
>> From: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
>>
>> It is possible to customize the axis display so change it to display
>> timestamps in seconds on the major axis (with six decimal spaces) and
>> millisecond offsets on the minor axis.
>>
>> v2:
>>   * Give up on broken relative timestamps.
>>
>> v3:
>>   * Drop all date complications and just use micro seconds throughout.
>>     (John Harrison)
>>
>> Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
>> Suggested-by: Chris Wilson <chris@chris-wilson.co.uk>
>> Cc: Chris Wilson <chris@chris-wilson.co.uk>
>> Cc: John Harrison <John.C.Harrison@Intel.com>
>> Reviewed-by: John Harrison <John.C.Harrison@Intel.com> # v2
>> ---
>>   scripts/trace.pl | 72 ++++++++++++++++++++++++++++++++----------------
>>   1 file changed, 48 insertions(+), 24 deletions(-)
>>
>> diff --git a/scripts/trace.pl b/scripts/trace.pl
>> index fc1713e4f9a7..3ad5effafd0a 100755
>> --- a/scripts/trace.pl
>> +++ b/scripts/trace.pl
>> @@ -329,20 +329,6 @@ sub sanitize_ctx
>>       }
>>   }
>> -sub ts
>> -{
>> -    my ($us) = @_;
>> -    my ($y, $mo, $d, $h, $m, $s);
>> -
>> -    $s = int($us / 1000000);
>> -    $us = $us % 1000000;
>> -
>> -    ($s, $m, $h, $d, $mo, $y) = gmtime($s);
>> -
>> -    return sprintf('%04u-%02u-%02u %02u:%02u:%02u.%06u',
>> -                $y, 1 + $mo, $d, $h, $m, $s, int($us));
>> -}
>> -
>>   # Main input loop - parse lines and build the internal 
>> representation of the
>>   # trace using a hash of requests and some auxilliary data structures.
>>   my $prev_freq = 0;
>> @@ -912,7 +898,7 @@ foreach my $key (sort sortQueue keys %db) {
>>           $style = 'color: black; background-color: ' .
>>                ctx_colour($ctx, 'queue');
>>           $content = "$name<br>$db{$key}->{'submit-delay'}us 
>> <small>($db{$key}->{'execute-delay'}us)</small>";
>> -        $startend = 'start: \'' . ts($queue) . '\', end: \'' . 
>> ts($submit) . '\'';
>> +        $startend = 'start: ' . $queue . ', end: ' . $submit;
>>           print "\t{id: $i, key: $skey, $type group: $group, subgroup: 
>> $subgroup, subgroupOrder: $subgroup, content: '$content', $startend, 
>> style: \'$style\'},\n";
>>           $i++;
>>       }
>> @@ -923,7 +909,7 @@ foreach my $key (sort sortQueue keys %db) {
>>           $style = 'color: black; background-color: ' .
>>                ctx_colour($ctx, 'ready');
>>           $content = 
>> "<small>$name<br>$db{$key}->{'execute-delay'}us</small>";
>> -        $startend = 'start: \'' . ts($submit) . '\', end: \'' . 
>> ts($start) . '\'';
>> +        $startend = 'start: ' . $submit . ', end: ' . $start;
>>           print "\t{id: $i, key: $skey, $type group: $group, subgroup: 
>> $subgroup, subgroupOrder: $subgroup, content: '$content', $startend, 
>> style: \'$style\'},\n";
>>           $i++;
>>       }
>> @@ -942,7 +928,7 @@ foreach my $key (sort sortQueue keys %db) {
>>           $content .= ' <small><i>++</i></small> ' if exists 
>> $db{$key}->{'no-end'};
>>           $content .= ' <small><i>+</i></small> ' if exists 
>> $db{$key}->{'no-notify'};
>>           $content .= "<br>$db{$key}->{'duration'}us 
>> <small>($db{$key}->{'context-complete-delay'}us)</small>";
>> -        $startend = 'start: \'' . ts($start) . '\', end: \'' . 
>> ts($notify) . '\'';
>> +        $startend = 'start: ' . $start . ', end: ' . $notify;
>>           print "\t{id: $i, key: $skey, $type group: $group, subgroup: 
>> $subgroup, subgroupOrder: $subgroup, content: '$content', $startend, 
>> style: \'$style\'},\n";
>>           $i++;
>>       }
>> @@ -956,7 +942,7 @@ foreach my $key (sort sortQueue keys %db) {
>>           $content .= ' <small><i>???</i></small> ' if exists 
>> $db{$key}->{'incomplete'};
>>           $content .= ' <small><i>++</i></small> ' if exists 
>> $db{$key}->{'no-end'};
>>           $content .= ' <small><i>+</i></small> ' if exists 
>> $db{$key}->{'no-notify'};
>> -        $startend = 'start: \'' . ts($notify) . '\', end: \'' . 
>> ts($end) . '\'';
>> +        $startend = 'start: ' . $notify . ', end: ' . $end;
>>           print "\t{id: $i, key: $skey, $type group: $group, subgroup: 
>> $subgroup, subgroupOrder: $subgroup, content: '$content', $startend, 
>> style: \'$style\'},\n";
>>           $i++;
>>       }
>> @@ -974,7 +960,7 @@ foreach my $item (@freqs) {
>>       $start = $first_ts if $start < $first_ts;
>>       $end = $last_ts if $end > $last_ts;
>> -    $startend = 'start: \'' . ts($start) . '\', end: \'' . ts($end) . 
>> '\'';
>> +    $startend = 'start: ' . $start . ', end: ' . $end;
>>       print "\t{id: $i, type: 'range', group: 0, content: '$freq', 
>> $startend},\n";
>>       $i++;
>>   }
>> @@ -988,18 +974,55 @@ if ($gpu_timeline) {
>>           $start = $first_ts if $start < $first_ts;
>>           $end = $last_ts if $end > $last_ts;
>> -        $startend = 'start: \'' . ts($start) . '\', end: \'' . 
>> ts($end) . '\'';
>> +        $startend = 'start: ' . $start . ', end: ' . $end;
>>           print "\t{id: $i, type: 'range', group: 1, $startend},\n";
>>           $i++;
>>       }
>>   }
>> -my $end_ts = ts($first_ts + $width_us);
>> -$first_ts = ts($first_ts);
>> +my $end_ts = $first_ts + $width_us;
>> +$first_ts = $first_ts;
>>   print <<ENDHTML;
>>     ]);
>> +  function majorAxis(date, scale, step) {
>> +    var s = date / 1000000;
>> +    var precision;
>> +
>> +    if (scale == 'millisecond')
>> +        precision = 6;
>> +    else if (scale == 'second')
>> +        precision = 3;
>> +    else
>> +        precision = 0;
>> +
>> +    return s.toFixed(precision) + "s";
>> +  }
>> +
>> +  function minorAxis(date, scale, step) {
>> +    var t = date;
>> +    var precision;
>> +    var unit;
>> +
>> +    if (scale == 'millisecond') {
>> +        t %= 1000;
>> +        precision = 0;
>> +        unit = 'us';
>> +    } else if (scale == 'second') {
>> +        t /= 1000;
>> +        t %= 1000;
>> +        precision = 0;
>> +        unit = 'ms';
>> +    } else {
>> +        t /= 1000000;
>> +        precision = 1;
>> +        unit = 's';
>> +    }
>> +
>> +    return t.toFixed(precision) + unit;
>> +  }
>> +
>>     // Configuration for the Timeline
>>     var options = { groupOrder: 'content',
>>             horizontalScroll: true,
>> @@ -1007,8 +1030,9 @@ print <<ENDHTML;
>>             stackSubgroups: false,
>>             zoomKey: 'ctrlKey',
>>             orientation: 'top',
>> -          start: '$first_ts',
>> -          end: '$end_ts'};
>> +          format: { majorLabels: majorAxis, minorLabels: minorAxis },
>> +          start: $first_ts,
>> +          end: $end_ts};
>>     // Create a Timeline
>>     var timeline = new vis.Timeline(container, items, groups, options);
> 
> Woohoo!
> 
> This one seems to work fine on both Firefox and Chrome. It even works on 
> IE and Edge unlike the previous version! I guess they can only cope with 
> raw times not dates!?
> 
> One thing I've just noticed is that there is also a 'now' line on the 
> timeline - a red vertical bar across the entire timeline. On the old 
> 'date' versions, it was following the current system time and hence 
> wandering forwards at one second per second. On this version, it is out 
> of position and advancing at one millisecond per second. Presumably 
> because you are scaling the axes by a factor of one thousand in order to 
> gain the necessary precision in the plot. Something of a curiosity but 
> certainly not a problem!

A moving red line? I never saw that! In any browser?

> Ship it :)

I have shipped it, thanks!

I have resent the remaining two unreviewed patches, plus two new ones. 
One is a fix for frequency timeline, and another is bringing back (now 
working) stacking button. (But it is off by default.)

Regards,

Tvrtko
John Harrison July 27, 2018, 10:22 p.m. UTC | #3
On 7/19/2018 2:39 AM, Tvrtko Ursulin wrote:
>
> On 18/07/2018 21:03, John Harrison wrote:
>>
>> One thing I've just noticed is that there is also a 'now' line on the 
>> timeline - a red vertical bar across the entire timeline. On the old 
>> 'date' versions, it was following the current system time and hence 
>> wandering forwards at one second per second. On this version, it is 
>> out of position and advancing at one millisecond per second. 
>> Presumably because you are scaling the axes by a factor of one 
>> thousand in order to gain the necessary precision in the plot. 
>> Something of a curiosity but certainly not a problem!
>
> A moving red line? I never saw that! In any browser?
>

You have to zoom out a long way to see it. The trace files are time 
stamped from system boot, so fairly low numbers of seconds. The 'now' 
line is referenced from 1/1/1970 or whenever (albeit in milliseconds 
rather than seconds now). So is massively far into the future compared 
to any of the log data.
diff mbox

Patch

diff --git a/scripts/trace.pl b/scripts/trace.pl
index fc1713e4f9a7..3ad5effafd0a 100755
--- a/scripts/trace.pl
+++ b/scripts/trace.pl
@@ -329,20 +329,6 @@  sub sanitize_ctx
 	}
 }
 
-sub ts
-{
-	my ($us) = @_;
-	my ($y, $mo, $d, $h, $m, $s);
-
-	$s = int($us / 1000000);
-	$us = $us % 1000000;
-
-	($s, $m, $h, $d, $mo, $y) = gmtime($s);
-
-	return sprintf('%04u-%02u-%02u %02u:%02u:%02u.%06u',
-		        $y, 1 + $mo, $d, $h, $m, $s, int($us));
-}
-
 # Main input loop - parse lines and build the internal representation of the
 # trace using a hash of requests and some auxilliary data structures.
 my $prev_freq = 0;
@@ -912,7 +898,7 @@  foreach my $key (sort sortQueue keys %db) {
 		$style = 'color: black; background-color: ' .
 			 ctx_colour($ctx, 'queue');
 		$content = "$name<br>$db{$key}->{'submit-delay'}us <small>($db{$key}->{'execute-delay'}us)</small>";
-		$startend = 'start: \'' . ts($queue) . '\', end: \'' . ts($submit) . '\'';
+		$startend = 'start: ' . $queue . ', end: ' . $submit;
 		print "\t{id: $i, key: $skey, $type group: $group, subgroup: $subgroup, subgroupOrder: $subgroup, content: '$content', $startend, style: \'$style\'},\n";
 		$i++;
 	}
@@ -923,7 +909,7 @@  foreach my $key (sort sortQueue keys %db) {
 		$style = 'color: black; background-color: ' .
 			 ctx_colour($ctx, 'ready');
 		$content = "<small>$name<br>$db{$key}->{'execute-delay'}us</small>";
-		$startend = 'start: \'' . ts($submit) . '\', end: \'' . ts($start) . '\'';
+		$startend = 'start: ' . $submit . ', end: ' . $start;
 		print "\t{id: $i, key: $skey, $type group: $group, subgroup: $subgroup, subgroupOrder: $subgroup, content: '$content', $startend, style: \'$style\'},\n";
 		$i++;
 	}
@@ -942,7 +928,7 @@  foreach my $key (sort sortQueue keys %db) {
 		$content .= ' <small><i>++</i></small> ' if exists $db{$key}->{'no-end'};
 		$content .= ' <small><i>+</i></small> ' if exists $db{$key}->{'no-notify'};
 		$content .= "<br>$db{$key}->{'duration'}us <small>($db{$key}->{'context-complete-delay'}us)</small>";
-		$startend = 'start: \'' . ts($start) . '\', end: \'' . ts($notify) . '\'';
+		$startend = 'start: ' . $start . ', end: ' . $notify;
 		print "\t{id: $i, key: $skey, $type group: $group, subgroup: $subgroup, subgroupOrder: $subgroup, content: '$content', $startend, style: \'$style\'},\n";
 		$i++;
 	}
@@ -956,7 +942,7 @@  foreach my $key (sort sortQueue keys %db) {
 		$content .= ' <small><i>???</i></small> ' if exists $db{$key}->{'incomplete'};
 		$content .= ' <small><i>++</i></small> ' if exists $db{$key}->{'no-end'};
 		$content .= ' <small><i>+</i></small> ' if exists $db{$key}->{'no-notify'};
-		$startend = 'start: \'' . ts($notify) . '\', end: \'' . ts($end) . '\'';
+		$startend = 'start: ' . $notify . ', end: ' . $end;
 		print "\t{id: $i, key: $skey, $type group: $group, subgroup: $subgroup, subgroupOrder: $subgroup, content: '$content', $startend, style: \'$style\'},\n";
 		$i++;
 	}
@@ -974,7 +960,7 @@  foreach my $item (@freqs) {
 
 	$start = $first_ts if $start < $first_ts;
 	$end = $last_ts if $end > $last_ts;
-	$startend = 'start: \'' . ts($start) . '\', end: \'' . ts($end) . '\'';
+	$startend = 'start: ' . $start . ', end: ' . $end;
 	print "\t{id: $i, type: 'range', group: 0, content: '$freq', $startend},\n";
 	$i++;
 }
@@ -988,18 +974,55 @@  if ($gpu_timeline) {
 
 		$start = $first_ts if $start < $first_ts;
 		$end = $last_ts if $end > $last_ts;
-		$startend = 'start: \'' . ts($start) . '\', end: \'' . ts($end) . '\'';
+		$startend = 'start: ' . $start . ', end: ' . $end;
 		print "\t{id: $i, type: 'range', group: 1, $startend},\n";
 		$i++;
 	}
 }
 
-my $end_ts = ts($first_ts + $width_us);
-$first_ts = ts($first_ts);
+my $end_ts = $first_ts + $width_us;
+$first_ts = $first_ts;
 
 print <<ENDHTML;
   ]);
 
+  function majorAxis(date, scale, step) {
+	var s = date / 1000000;
+	var precision;
+
+	if (scale == 'millisecond')
+		precision = 6;
+	else if (scale == 'second')
+		precision = 3;
+	else
+		precision = 0;
+
+	return s.toFixed(precision) + "s";
+  }
+
+  function minorAxis(date, scale, step) {
+	var t = date;
+	var precision;
+	var unit;
+
+	if (scale == 'millisecond') {
+		t %= 1000;
+		precision = 0;
+		unit = 'us';
+	} else if (scale == 'second') {
+		t /= 1000;
+		t %= 1000;
+		precision = 0;
+		unit = 'ms';
+	} else {
+		t /= 1000000;
+		precision = 1;
+		unit = 's';
+	}
+
+	return t.toFixed(precision) + unit;
+  }
+
   // Configuration for the Timeline
   var options = { groupOrder: 'content',
 		  horizontalScroll: true,
@@ -1007,8 +1030,9 @@  print <<ENDHTML;
 		  stackSubgroups: false,
 		  zoomKey: 'ctrlKey',
 		  orientation: 'top',
-		  start: '$first_ts',
-		  end: '$end_ts'};
+		  format: { majorLabels: majorAxis, minorLabels: minorAxis },
+		  start: $first_ts,
+		  end: $end_ts};
 
   // Create a Timeline
   var timeline = new vis.Timeline(container, items, groups, options);