User:Jdev/Code/TimeProfiler

From Robowiki
Jump to navigation Jump to search

It's utility class for robots time profiling. Feel free to adopt and/or use it

Code:

package lxx.utils.time_profiling;

import lxx.utils.ValueInfo;

import static java.lang.StrictMath.max;

public enum TimeProfile {

    TURN_TIME;

    private ValueInfo battleProfile;
    private ValueInfo roundProfile;
    private ValueInfo turnProfile;

    private long startTime = -1;

    public void start() {
        if (startTime != -1) {
            System.out.printf("[WARN] %s: Stop was not called\n", this.name());
            return;
        }
        startTime = System.nanoTime();
    }

    public void stop() {
        if (startTime == -1) {
            System.out.printf("[WARN] %s: Start was not called\n", this.name());
            return;
        }
        final long time = System.nanoTime() - startTime;
        battleProfile.addValue(time);
        roundProfile.addValue(time);
        turnProfile.addValue(time);
        startTime = -1;
    }

    public static void initBattle() {
        for (TimeProfile tp : values()) {
            tp.battleProfile = new ValueInfo(1500000);
        }
    }

    public static void initRound() {
        for (TimeProfile tp : values()) {
            tp.roundProfile = new ValueInfo(60000);
        }
    }

    public static void initTurn() {
        for (TimeProfile tp : values()) {
            tp.turnProfile = new ValueInfo(300);
        }
    }

    public static String getBattleProfilesString() {
        final StringBuilder res = new StringBuilder(" == Battle Time Profiles == \n");
        int maxPropertyNameLength = getMaxNameLen();
        for (TimeProfile tp : values()) {
            res.append(" ").append(String.format("%" + maxPropertyNameLength + "s", tp.name())).append(": ").append(tp.battleProfile.toString()).append("\n");
        }
        return res.toString();
    }

    public static String getRoundProfilesString() {
        final StringBuilder res = new StringBuilder(" == Round Time Profiles == \n");
        int maxPropertyNameLength = getMaxNameLen();
        for (TimeProfile tp : values()) {
            res.append(" ").append(String.format("%" + maxPropertyNameLength + "s", tp.name())).append(": ").append(tp.roundProfile.toString()).append("\n");
        }
        return res.toString();
    }

    public static String getTurnProfilesString() {
        final StringBuilder res = new StringBuilder(" == Turn Time Profiles == \n");
        int maxPropertyNameLength = getMaxNameLen();
        for (TimeProfile tp : values()) {
            res.append(" ").append(String.format("%" + maxPropertyNameLength + "s", tp.name())).append(": ").append(tp.turnProfile.toString()).append("\n");
        }
        return res.toString();
    }

    private static int getMaxNameLen() {
        int maxNameLen = 0;

        for (TimeProfile tp : values()) {
            maxNameLen = max(maxNameLen, tp.name().length());
        }

        return maxNameLen;
    }

}

package lxx.utils;

import static java.lang.Math.max;
import static java.lang.StrictMath.min;

public class ValueInfo {

    private final AvgValue avgValue;
    private double maxValue = Long.MIN_VALUE;
    private double minValue = Long.MAX_VALUE;
    private double total;

    public ValueInfo(int deph) {
        avgValue = new AvgValue(deph);
    }

    public void addValue(double value) {
        maxValue = max(maxValue, value);
        minValue = min(minValue, value);
        avgValue.addValue(value);
        total += value;
    }

    @Override
    public String toString() {
        if (maxValue == Long.MIN_VALUE) {
            return "[ No Data ]";
        } else if (maxValue == minValue) {
            return String.format("[ %,14.0f ]", minValue);
        } else {
            return String.format("[ %,9.0f | %,9.0f | %,14.0f | %,20.0f]", minValue, avgValue.getCurrentValue(), maxValue, total);
        }
    }
}

package lxx.utils;

import static java.lang.Math.min;

public class AvgValue {

    private final double[] values;
    private final int depth;
    private int valuesCount;
    private double currentSum;
    private double currentValue;

    public AvgValue(int depth) {
        this.depth = depth;
        values = new double[depth];
    }

    public void addValue(double newValue) {
        currentSum = currentSum - values[valuesCount % values.length] + newValue;
        values[valuesCount % values.length] = newValue;
        valuesCount++;
        currentValue = currentSum / min(valuesCount, depth);
    }

    public double getCurrentValue() {
        return currentValue;
    }

    public String toString() {
        return String.format("Avg value = %10.5f", getCurrentValue());
    }
}

Usage (typed in browser, so may contains errors):

public class TPRobot extends AdvancedRobot {

    static {
        TimeProfile.initBattle();
    }

    public void run() {
        TimeProfile.initRound();
        while (true) {
            TimeProfile.initTurn();
            TimeProfile.TURN_TIME.start();
            // robot code
            TimeProfile.TURN_TIME.stop();
            execute();
        }
    }

    public void onDeath(DeathEvent event) {
        System.out.println(TimeProfile.getRoundProfilesString());
        System.out.println(TimeProfile.getBattleProfilesString());
    }

    public void onWin(WinEvent event) {
        System.out.println(TimeProfile.getRoundProfilesString());
        System.out.println(TimeProfile.getBattleProfilesString());
    }

    public void onSkippedTurn(SkippedTurnEvent event) {
        System.out.println(TimeProfile.getTurnProfilesString());
    }

}

Output example:

 == Round Time Profiles == 
                   TURN_TIME: [    31 451 |   720 724 |     33 814 642 |        1 457 304 116]
      PROCESS_LISTENERS_TIME: [    24 830 |   339 116 |     33 614 018 |          685 691 651]
               EBM_WAVE_TIME: [   556 183 | 1 763 225 |     32 754 914 |          297 984 994]
 SELECT_ORBIT_DIRECTION_TIME: [    54 956 |   391 181 |      1 212 348 |          362 233 454]
                    GUN_TIME: [ 1 524 870 | 1 916 700 |      3 495 349 |          327 755 712]
        TR_RANGE_SEARCH_TIME: [     1 325 |    31 450 |     31 329 693 |          308 243 570]
                TR_SORT_TIME: [         0 |    20 288 |        748 531 |          248 448 312]
               MOVEMENT_TIME: [     2 980 |   212 053 |      1 720 527 |          428 347 163]

 == Battle Time Profiles == 
                   TURN_TIME: [     9 269 |   524 517 |     36 706 135 |       28 108 844 538]
      PROCESS_LISTENERS_TIME: [     6 290 |   207 137 |     36 682 630 |       11 100 497 548]
               EBM_WAVE_TIME: [   149 970 |   991 202 |     34 882 647 |        4 173 953 087]
 SELECT_ORBIT_DIRECTION_TIME: [    14 567 |   388 092 |     33 676 920 |        9 231 536 613]
                    GUN_TIME: [   245 648 | 1 458 686 |     34 828 353 |        6 219 835 279]
        TR_RANGE_SEARCH_TIME: [       331 |    17 518 |     35 778 500 |        4 177 437 515]
                TR_SORT_TIME: [         0 |    11 702 |      3 681 737 |        3 044 313 750]
               MOVEMENT_TIME: [     1 655 |   198 914 |     33 693 142 |       10 390 890 834]