Library globals

Source performance_monitor . monitor.nas

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
# GUI displaying FG system performance statistics 
# performance_monitor.dialog.show() -- displays pilot list dialog

var PERFMON_RUNNING = 0;

var dialog = {
    init: func(x = nil, y = nil) {
        me.x = x;
        me.y = y;
        me.bg = [0, 0, 0, 0.3];    # background color
        me.fg = [[0.9, 0.9, 0.2, 1], [1, 1, 1, 1]]; # alternative active

        # "private"
        var font = { name: getprop("/sim/gui/selected-style/fonts/mp-list/name") or "FIXED_8x13", 
                       size: getprop("/sim/gui/selected-style/fonts/mp-list/size") or 20, 
                       slant: getprop("/sim/gui/selected-style/fonts/mp-list/slant") or 0, 
                     };
        me.header = ["  submodule", "cumulative/ms", "total/ms", "max/ms", "min/ms", "mean/ms", "stddev/ms", "iterations" ];
        me.columns = [
            { type: "text", property: "name",          format:   " %s", label: "------------------", halign: "fill", font: font },
            { type: "text", property: "cumulative-ms", format: "%9.2f", label: "-------------",      halign: "fill", font: font },
            { type: "text", property: "total-ms",      format: "%6.2f", label: "----------",         halign: "fill", font: font },
            { type: "text", property: "max-ms",        format: "%5.2f", label: "---------",          halign: "fill", font: font },
            { type: "text", property: "min-ms",        format: "%5.2f", label: "---------",          halign: "fill", font: font },
            { type: "text", property: "mean-ms",       format: "%5.2f", label: "---------",          halign: "fill", font: font },
            { type: "text", property: "stddev-ms",     format: "%5.2f", label: "---------",          halign: "fill", font: font },
            { type: "text", property: "count",         format: "%3d",   label: "------",             halign: "fill", font: font },
        ];
        me.name = "performance-monitor";
        me.dialog = nil;
        me.loopid = 0;

        me.listeners=[];
        append(me.listeners, setlistener("/sim/startup/xsize", func me._redraw_()));
        append(me.listeners, setlistener("/sim/startup/ysize", func me._redraw_()));
        append(me.listeners, setlistener("/sim/signals/reinit-gui", func me._redraw_()));
    },
    create: func {
        if (me.dialog != nil)
            me.close();

        setprop("/sim/performance-monitor/enabled",1);

        me.dialog = gui.dialog[me.name] = gui.Widget.new();
        me.dialog.set("name", me.name);
        me.dialog.set("dialog-name", me.name);
        if (me.x != nil)
            me.dialog.set("x", me.x);
        if (me.y != nil)
            me.dialog.set("y", me.y);

        me.dialog.set("layout", "vbox");
        me.dialog.set("default-padding", 0);

        me.dialog.setColor(me.bg[0], me.bg[1], me.bg[2], me.bg[3]);

        var titlebar = me.dialog.addChild("group");
        titlebar.set("layout", "hbox");

        var w = titlebar.addChild("button");
        w.node.setValues({ "pref-width": 32, "pref-height": 16, legend: "sort", default: 0 });
        w.setBinding("nasal", "performance_monitor.dialog._redraw_()");

        titlebar.addChild("empty").set("stretch", 1);
        titlebar.addChild("text").set("label", "worst/average frame rate: ");
        titlebar.addChild("text").node.setValues({ live: 1, property: "/sim/frame-rate-worst", label: "--" });
        titlebar.addChild("text").set("label", "/");
        titlebar.addChild("text").node.setValues({ live: 1, property: "/sim/frame-rate", label: "-- fps,", format: "%2d fps," });
        titlebar.addChild("text").set("label", " worst frame delay: ");
        titlebar.addChild("text").node.setValues({ live: 1, property: "/sim/frame-latency-max-ms", label: "----.-", format: "%4d ms" });
        titlebar.addChild("empty").set("stretch", 1);

        var w = titlebar.addChild("button");
        w.node.setValues({ "pref-width": 16, "pref-height": 16, legend: "", default: 0 });
        # "Esc" causes dialog-close
        w.set("key", "Esc");
        w.setBinding("nasal", "performance_monitor.dialog.del()");

        me.dialog.addChild("hrule");

        var content = me.dialog.addChild("group");
        content.set("layout", "table");
        content.set("default-padding", 0);

        var modulelist = props.globals.getNode( "/sim/performance-monitor/subsystems", 1 ).getChildren();
        var DataReady = size(modulelist) > 0;
        if (!DataReady)
        {
            content.addChild("text").set("label", "wait...");
        }
        else
        {
            var row = 0;
            var col = 0;
            foreach (var h; me.header) {
                var w = content.addChild("text");
                var l = typeof(h) == "func" ? h() : h;
                w.node.setValues({ "label": l, "row": row, "col": col, halign: me.columns[col].halign });
                w = content.addChild("hrule");
                w.node.setValues({ "row": row + 1, "col": col });
                col += 1;
            }
            row += 2;
            var odd = 1;
            modulelist = sort (modulelist, func (a,b) a.getChild("cumulative-ms",0,1).getValue() < b.getChild("cumulative-ms",0,1).getValue());
            foreach (var mp; modulelist) {
                var col = 0;
                var color = me.fg[odd = !odd];
                foreach (var column; me.columns) {
                    var p = column.property;
                    var w = nil;
                    if (column.type == "text") {
                        w = content.addChild("text");
                        w.node.setValues(column);
                    }
                    w.setColor(color[0], color[1], color[2], color[3]);
                    w.node.setValues({ row: row, col: col, live: 1, property: mp.getPath() ~ "/" ~ p });
                    col += 1;
                }
                row += 1;
            }
        }
        if (me.x != nil)
            me.dialog.set("x", me.x);
        if (me.y != nil)
            me.dialog.set("y", me.y);

        fgcommand("dialog-new", me.dialog.prop());
        fgcommand("dialog-show", me.dialog.prop());
        if (!DataReady)
            settimer(func me.update(me.loopid+=1), 1, 1);
    },
    update: func(id) {
        id == me.loopid or return;
        if (!PERFMON_RUNNING)
            return;
        me._redraw_();
    },
    _redraw_: func {
        if (me.dialog != nil) {
            me.close();
            me.create();
        }
    },
    close: func {
        if (me.dialog != nil) {
            me.x = me.dialog.prop().getNode("x").getValue();
            me.y = me.dialog.prop().getNode("y").getValue();
        }
        fgcommand("dialog-close", me.dialog.prop());
        setprop("/sim/performance-monitor/enabled",0);
    },
    del: func {
        PERFMON_RUNNING = 0;
        me.close();
        foreach (var l; me.listeners)
            removelistener(l);
        delete(gui.dialog, me.name);
    },
    show: func {
        if (!PERFMON_RUNNING) {
            PERFMON_RUNNING = 1;
            me.init(2, 20);
            me.create();
        }
    },
    toggle: func {
        if (!PERFMON_RUNNING)
            me.show();
        else
            me.del();
    },
};