hxtelemetry
hxtelemetry copied to clipboard
Documentation for new framework support
Inspired by #66, I've written this SampleFramework as a semi-realistic example for how to add HxTelemetry support to any Haxe framework. (It could also be referenced for how to add support to an app, though presumably an app wouldn't have hooks to add the necessary start / stop timing calls to measure low-level activities, e.g. rendering time. But it could probably do advance_frame()
, and some user-specific activities.)
TODO: publish the to hxscout.com or this repo's wiki
Notice that the framework can define what activities it wants to measure (typically "render" is a common one, perhaps others like "scripting" or "user" might be typical), and it gets to define what color and what label show up in the hxScout GUI for those activities. Below, SampleFramework defines Render as green and Something as purple.
package;
#if (hxtelemetry)
import hxtelemetry.HxTelemetry;
#end
#if (hxtelemetry)
// These are the "activities" I want to measure in my framework:
@:enum abstract SampleFrameworkActivityNames(String) to String {
var T_RENDER = '.render';
var T_SOMETHING = '.something';
}
#end
class SampleFramework
{
public function new()
{
trace('new SampleFramework');
#if (hxtelemetry)
// Is blocking, tries 3 times to connect to hxscout, then gives up
init_telemetry();
#end
// Assume some processing is typical at time 0
trace(do_some_string_processing(5000));
haxe.MainLoop.add(on_frame);
}
// I instrument this as my T_SOMETHING activity
function do_some_string_processing(upto:Int)
{
#if (hxtelemetry)
// Measure some other activity during a frame
_hxtelemetry.start_timing(T_SOMETHING);
#end
var sum = 0;
var wasteful = '{"hello":"world"}';
for (i in 0...upto) {
var obj = haxe.Json.parse(wasteful);
sum += Reflect.field(obj, "hello").length;
}
#if (hxtelemetry)
// Measure some other activity during a frame
_hxtelemetry.end_timing(T_SOMETHING);
#end
return 'Parsed to $sum';
}
#if (hxtelemetry)
var _hxtelemetry:HxTelemetry;
function init_telemetry()
{
// Optionally verify the necessary defines. For hxcpp, it's:
#if (hxtelemetry && cpp)
#if (!(HXCPP_TELEMETRY && HXCPP_STACK_TRACE))
#error "Error: cannot use hxtelemetry without -D HXCPP_TELEMETRY and -D HXCPP_STACK_TRACE"
#end
#end
// Setup your hxtelemetry instance
var cfg = new hxtelemetry.HxTelemetry.Config();
cfg.activity_descriptors = [
{name: T_SOMETHING, description: "Something", color: 0xaa33bb},
{name: T_RENDER, description: "Render", color: 0x66aa66}
];
// Advanced feature: you could allow your end users to define their own activity
// definitions, and simply push them into the above array of activity_descriptors.
// They would also need hooks for calling start_timing / end_timing.
// Maybe provide your users some kind of configuration for these parameters:
cfg.app_name = "SampleFramework App"; // Maybe your user names their app?
cfg.host = "localhost";
cfg.port = 7934;
cfg.cpu_usage = true;
cfg.profiler = true;
cfg.trace = true;
// Allocation tracking is an expensive setting, and will impact your app's performance.
// It should only be used to debug memory issues:
cfg.allocations = true;
trace('HxTelemetry initializing... will try to connect to ${ cfg.host }:${ cfg.port }');
_hxtelemetry = new HxTelemetry(cfg);
}
#end
// Sample Framework's Main Loop
var frame_cnt = 0;
private function on_frame()
{
trace('on_frame ${ frame_cnt++ }');
var t0 = haxe.Timer.stamp();
#if (hxtelemetry)
// Measure rendering time during a frame
_hxtelemetry.start_timing(T_RENDER);
#end
Sys.sleep(0.006); // fake time spent
#if (hxtelemetry)
_hxtelemetry.end_timing(T_RENDER);
#end
trace(do_some_string_processing(1000));
// Lock to 60fps by sleeping remainder of 16 ms - this will show up in
// hxScout as a consistent 60 fps frame time (gray / no activity)
var dt = haxe.Timer.stamp() - t0;
if (dt < 0.016) Sys.sleep(0.016 - dt);
#if (hxtelemetry)
_hxtelemetry.advance_frame();
#end
if (frame_cnt==100) {
trace('Finished!');
Sys.exit(0);
}
}
public static function main()
{
new SampleFramework();
}
}
Run with:
> haxe -main SampleFramework -lib hxtelemetry -D HXCPP_TELEMETRY -D HXCPP_STACK_TRACE -cpp out
> ./out/SampleFramework
The resulting hxScout screenshot is below.
Notice the green Render activity, the purple Something activity, as well as the built-in red garbage collector activity, and the consistent / locked 60-fps (remainder of gray.) Also, since I'm doing wasteful JSON parsing each frame (wastefully allocating and destroying objects and strings), I occasionally get a big GC spike that pushes me above my 16ms frame budget.