com.madvay.tools.android.perf.apat.Main.java Source code

Java tutorial

Introduction

Here is the source code for com.madvay.tools.android.perf.apat.Main.java

Source

/*
 * Copyright (c) 2015 by Advay Mengle.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package com.madvay.tools.android.perf.apat;

import com.madvay.tools.android.perf.BuildInfo;
import com.madvay.tools.android.perf.allocs.AllocRow;
import com.madvay.tools.android.perf.allocs.AllocTable;
import com.madvay.tools.android.perf.allocs.AllocationsParserAdapter;
import com.madvay.tools.android.perf.allocs.PrettyAllocRowOutput;
import com.madvay.tools.android.perf.common.*;

import com.google.common.base.Charsets;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.io.Resources;

import java.io.IOException;
import java.util.List;
import java.util.Map;

/**
 *
 */
public class Main {

    private static void outln(String s) {
        System.out.println(s);
    }

    private static void out(String s) {
        System.out.print(s);
    }

    private static void err(String s) {
        System.out.println("Error: " + s + "\n");
        System.out.flush();
    }

    private static void err(Exception e) {
        err(e.getMessage());
        e.printStackTrace();
    }

    private static void printUsage() {
        try {
            List<String> lines = Resources.readLines(Resources.getResource("README.txt"), Charsets.UTF_8);
            boolean foundUsage = false, foundBeginHash = false;

            /*
             * We want to output the lines of usage in the README.md file:
                
            <other stuff>
            ## Usage
            ```
            <stuff to display>
            ```
            <other stuff>
                
             */
            lineLoop: for (String l : lines) {
                if (foundUsage) {
                    if (foundBeginHash) {
                        if (l.equals("```")) {
                            // end!
                            break lineLoop;
                        }
                        outln(l);
                    }
                    if (l.equals("```")) {
                        foundBeginHash = true;
                    }
                }
                if (l.equals("## Usage")) {
                    foundUsage = true;
                }
            }
        } catch (IOException err) {
            err(err);
        }
    }

    private static void printLicense() {
        try {
            List<String> lines = Resources.readLines(Resources.getResource("LICENSE"), Charsets.UTF_8);
            for (String l : lines) {
                outln(l);
            }
        } catch (IOException err) {
            err(err);
        }
    }

    private static void printVersion() {
        outln(String.format("apat Version %s\n  Built at %s\n  On commit %s\n  Url: %s", BuildInfo.VERSION,
                BuildInfo.TIMESTAMP, BuildInfo.GIT_COMMIT, BuildInfo.URL));
        if (BuildInfo.VERSION.contains("SNAPSHOT")) {
            outln("*** Note: This is an unofficial snapshot release.");
            outln("*** See https://madvay.com/source/apat for official releases.");
        }
        if (!BuildInfo.GIT_IS_CLEAN) {
            outln("!!! Warning: This unofficial build was made with local modifications.");
            outln("!!! See https://madvay.com/source/apat for official releases.");
        }
        outln("---------------------------------------------------------------");
        try {
            List<String> lines = Resources.readLines(Resources.getResource("NOTICE"), Charsets.UTF_8);
            for (String l : lines) {
                outln(l);
            }
        } catch (IOException err) {
            err(err);
        }
    }

    public static void main(String[] argv) {
        CommandLine cmd = null;
        try {
            cmd = new CommandLine(argv);
        } catch (IllegalArgumentException e) {
            err(e.getMessage());
            printUsage();
            System.exit(-1);
            return;
        }

        try {
            switch (cmd.command) {
            case "help":
                printUsage();
                break;
            case "version":
                printVersion();
                break;
            case "license":
                printLicense();
                break;
            case "allocs":
                runAllocs(cmd);
                break;
            default:
                throw new IllegalArgumentException("Unknown command: " + cmd.command);
            }
        } catch (Exception e) {
            err(e.getMessage());
            e.printStackTrace(System.out);
            printUsage();
            System.exit(-1);
        }
        return;
    }

    private static <T extends TraceTransformableRow> void //
            runAllocsListProcessing(CommandLine cmd, TraceTransformableTable<T> table) {
        tableTraceTransform(cmd, table);
        tableTraceSplit(cmd, table);
        tableRowsFilter(cmd, table);
        tableRowsSample(cmd, table);
        tableRowsSort(cmd, table);
    }

    private static <T extends TraceTransformableRow> Table<AggregateRow> //
            runAllocsTopProcessing(CommandLine cmd, TraceTransformableTable<T> table) {
        tableTraceTransform(cmd, table);
        tableTraceSplit(cmd, table);
        tableRowsFilter(cmd, table);
        String groupBy = cmd.getUnaryFlagWithDefault("groupBy", "allocatorMethod");
        String weight = cmd.getUnaryFlagWithDefault("weight", "size");

        Table<AggregateRow> agg = table.groupAndAggregate(groupBy, weight,
                weight.equals("size") ? Table.AggregationType.SUM
                        : weight.equals("id") ? Table.AggregationType.COUNT : Table.AggregationType.UNIQUE);
        tableRowsSort(cmd, agg, ImmutableList.of("-weight", "group"));
        return agg;
    }

    private static <T extends Row> void tableRowsSort(CommandLine cmd, Table<T> table) {
        tableRowsSort(cmd, table, ImmutableList.<String>of());
    }

    private static <T extends Row> void tableRowsSample(CommandLine cmd, Table<T> table) {
        table.sample(Integer.parseInt(cmd.getUnaryFlagWithDefault("samples", "-1")));
    }

    private static <T extends Row> void tableRowsSort(CommandLine cmd, Table<T> table, List<String> defaultSort) {
        List<String> sort = cmd.getMultiFlagWithInternalLists("sort");
        if (!sort.isEmpty()) {
            table.sortOn(sort);
        } else if (!defaultSort.isEmpty()) {
            table.sortOn(defaultSort);
        }
    }

    private static <T extends Row> void tableRowsFilter(CommandLine cmd, Table<T> table) {
        for (String key : table.getAdapter().columns) {
            for (FilterSpec spec : cmd.getFilterSpecsFlag(key)) {
                table.matching(spec);
            }
        }
    }

    private static <T extends TraceTransformableRow> void tableTraceSplit(CommandLine cmd,
            TraceTransformableTable<T> table) {
        if (Boolean.parseBoolean(cmd.getUnaryFlagWithDefault("splitByTrace", "false"))) {
            table.splitTraces();
        }
    }

    private static <T extends TraceTransformableRow> void tableTraceTransform(CommandLine cmd,
            TraceTransformableTable<T> table) {
        for (TraceTransformers.TT tt : cmd.getTraceTransformsFlag("traceTransform")) {
            table.transformTraces(tt);
        }
    }

    private static <T extends Row> TableFormatter<T> //
            pickFormatter(CommandLine cmd, Map<String, Function<? super T, String>> formatters) {
        // Output
        String fmt = cmd.getUnaryFlagWithDefault("format", "pretty");
        return new TableFormatter<>(formatters.get(fmt));
    }

    private static void runAllocs(CommandLine cmd) {
        AllocTable table = new AllocTable(AllocationsParserAdapter.parse(cmd.args.get(1)));
        switch (cmd.args.get(0)) {
        case "list": {
            runAllocsList(cmd, table);
            break;
        }
        case "top": {
            runAllocsTop(cmd, table);
            break;
        }
        default:
            throw new IllegalArgumentException("Unknown allocs subcommand: " + cmd.args.get(0));
        }
    }

    private static void runAllocsTop(CommandLine cmd, AllocTable table) {
        Table<AggregateRow> aggTable = runAllocsTopProcessing(cmd, table);
        TableFormatter<AggregateRow> fmt = pickFormatter(cmd,
                ImmutableMap.<String, Function<? super AggregateRow, String>>of( //
                        "csv", new CsvOutput<>(aggTable.getAdapter().columns, aggTable.getAdapter()), //
                        "pretty", new PrettyAggregateRowOutput(aggTable)));
        out(fmt.format(aggTable));
    }

    private static void runAllocsList(CommandLine cmd, AllocTable table) {
        runAllocsListProcessing(cmd, table);
        TableFormatter<AllocRow> fmt = pickFormatter(cmd,
                ImmutableMap.<String, Function<? super AllocRow, String>>of( //
                        "csv", new CsvOutput<>(table.getAdapter().columns, table.getAdapter()), //
                        "pretty", new PrettyAllocRowOutput()));
        out(fmt.format(table));
    }
}