DEV Community

Charlie Fubon
Charlie Fubon

Posted on

F1


import java.io.*;
import java.nio.charset.Charset;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

public class WeightedPerformanceAnalyzer {

    // Pattern 1: WebApplicationContext initialization
    private static final Pattern INIT_PATTERN = Pattern.compile("WebApplicationContext: initialization completed in (\\d+) ms");

    // Pattern 2: Method execution with asterisks format
    private static final Pattern METHOD_PATTERN_1 = Pattern.compile("\\*\\|\\s*\\*Time taken for\\*\\|\\*(.*?)\\*\\|\\*is\\*\\|\\*(\\d+)\\*\\|\\*ms");

    // Pattern 3: Method execution without asterisks or with different formatting
    private static final Pattern METHOD_PATTERN_2 = Pattern.compile("Time taken for(.*?)is(\\d+)\\s*ms");

    // Additional fallback patterns to catch other variations
    private static final Pattern[] FALLBACK_PATTERNS = {
        Pattern.compile("Time taken for\\s+(.*?)\\s+is\\s+(\\d+)\\s+ms"),
        Pattern.compile("took\\s+(\\d+)\\s+ms"),
        Pattern.compile("execution time:\\s+(\\d+)\\s+ms"),
        Pattern.compile("completed in\\s+(\\d+)\\s+ms")
    };

    static class TimingInfo {
        String category;
        String operation;
        int timeInMs;
        String source; // Which pattern found this

        TimingInfo(String category, String operation, int timeInMs, String source) {
            this.category = category;
            this.operation = operation;
            this.timeInMs = timeInMs;
            this.source = source;
        }

        @Override
        public String toString() {
            return category + " - " + operation + ": " + timeInMs + " ms [" + source + "]";
        }
    }

    static class PerformanceMetrics {
        String operation;
        List<Integer> beforeTimes = new ArrayList<>();
        List<Integer> afterTimes = new ArrayList<>();
        double weightedBeforeAvg;
        double weightedAfterAvg;
        double improvementPercent;
        int beforeCount;
        int afterCount;

        public PerformanceMetrics(String operation) {
            this.operation = operation;
        }

        public void calculateWeightedAverages() {
            this.beforeCount = beforeTimes.size();
            this.afterCount = afterTimes.size();

            // Calculate weighted averages - weight by frequency of occurrence
            this.weightedBeforeAvg = calculateWeightedAverage(beforeTimes);
            this.weightedAfterAvg = calculateWeightedAverage(afterTimes);

            // Calculate improvement percentage
            if (weightedBeforeAvg > 0) {
                this.improvementPercent = ((weightedBeforeAvg - weightedAfterAvg) / weightedBeforeAvg) * 100;
            } else {
                this.improvementPercent = 0;
            }
        }

        private double calculateWeightedAverage(List<Integer> times) {
            if (times.isEmpty()) return 0;

            // Group values to count frequencies
            Map<Integer, Integer> valueFrequency = new HashMap<>();
            for (int time : times) {
                valueFrequency.put(time, valueFrequency.getOrDefault(time, 0) + 1);
            }

            double weightedSum = 0;
            int totalWeight = 0;

            for (Map.Entry<Integer, Integer> entry : valueFrequency.entrySet()) {
                int value = entry.getKey();
                int frequency = entry.getValue();

                weightedSum += (value * frequency);
                totalWeight += frequency;
            }

            return totalWeight > 0 ? weightedSum / totalWeight : 0;
        }
    }

    public static void main(String[] args) {
        // File paths
        String[] beforeFiles = {"Jan29log.txt", "Jan30log.txt", "Jan31log.txt"};
        String[] afterFiles = {"Feb25thlog.txt", "Feb26thlog.txt", "Feb27thlog.txt"};

        try {
            // Process files and collect timing data
            List<TimingInfo> beforeTimings = new ArrayList<>();
            System.out.println("PROCESSING BEFORE UPGRADE FILES:");
            for (String file : beforeFiles) {
                List<TimingInfo> timings = processFile(file);
                beforeTimings.addAll(timings);
            }

            List<TimingInfo> afterTimings = new ArrayList<>();
            System.out.println("\nPROCESSING AFTER UPGRADE FILES:");
            for (String file : afterFiles) {
                List<TimingInfo> timings = processFile(file);
                afterTimings.addAll(timings);
            }

            // Calculate weighted performance metrics
            Map<String, PerformanceMetrics> performanceData = calculatePerformanceMetrics(beforeTimings, afterTimings);

            // Generate the reports
            printTopPerformers(performanceData, 10);
            printWorstPerformers(performanceData, 10);
            printOverallPerformance(performanceData);

        } catch (Exception e) {
            System.out.println("Error: " + e.getMessage());
            e.printStackTrace();
        }
    }

    private static List<TimingInfo> processFile(String filename) {
        List<TimingInfo> timings = new ArrayList<>();
        File file = new File(filename);

        if (!file.exists()) {
            System.out.println("  " + filename + " not found");
            return timings;
        }

        System.out.println("  Processing " + filename);

        // Track counts for each pattern
        int pattern1Count = 0;
        int pattern2Count = 0;
        int pattern3Count = 0;
        int fallbackCount = 0;

        try {
            // Use UTF-16LE encoding as discovered is critical
            BufferedReader reader = new BufferedReader(
                new InputStreamReader(new FileInputStream(file), Charset.forName("UTF-16LE")));

            String line;
            int lineCount = 0;

            while ((line = reader.readLine()) != null) {
                lineCount++;

                // Try Pattern 1: WebApplicationContext initialization
                Matcher matcher1 = INIT_PATTERN.matcher(line);
                if (matcher1.find()) {
                    int time = Integer.parseInt(matcher1.group(1));
                    timings.add(new TimingInfo("Initialization", "WebApplicationContext", time, "Pattern1"));
                    pattern1Count++;
                    continue;
                }

                // Try Pattern 2: Method execution with asterisks
                Matcher matcher2 = METHOD_PATTERN_1.matcher(line);
                if (matcher2.find()) {
                    String operation = matcher2.group(1).trim();
                    int time = Integer.parseInt(matcher2.group(2));
                    timings.add(new TimingInfo("Method Execution", operation, time, "Pattern2"));
                    pattern2Count++;
                    continue;
                }

                // Try Pattern 3: Method execution without asterisks
                Matcher matcher3 = METHOD_PATTERN_2.matcher(line);
                if (matcher3.find()) {
                    String operation = matcher3.group(1).trim();
                    int time = Integer.parseInt(matcher3.group(2));
                    timings.add(new TimingInfo("Method Execution", operation, time, "Pattern3"));
                    pattern3Count++;
                    continue;
                }

                // Try fallback patterns if none of the above matched
                for (int i = 0; i < FALLBACK_PATTERNS.length; i++) {
                    Matcher fallbackMatcher = FALLBACK_PATTERNS[i].matcher(line);
                    if (fallbackMatcher.find()) {
                        String operation = "Unknown";
                        int time;

                        // Get operation name if available (pattern dependent)
                        if (fallbackMatcher.groupCount() >= 2) {
                            operation = fallbackMatcher.group(1).trim();
                            time = Integer.parseInt(fallbackMatcher.group(2));
                        } else {
                            time = Integer.parseInt(fallbackMatcher.group(1));
                        }

                        if (line.contains("init") || line.contains("context")) {
                            timings.add(new TimingInfo("Initialization", operation, time, "Fallback" + i));
                        } else {
                            timings.add(new TimingInfo("Method Execution", operation, time, "Fallback" + i));
                        }
                        fallbackCount++;
                        break;
                    }
                }
            }
            reader.close();

            System.out.println("    Processed " + lineCount + " lines");
            System.out.println("    Pattern 1 (WebApplicationContext): " + pattern1Count + " matches");
            System.out.println("    Pattern 2 (Method with *): " + pattern2Count + " matches");
            System.out.println("    Pattern 3 (Method without *): " + pattern3Count + " matches");
            System.out.println("    Fallback patterns: " + fallbackCount + " matches");
            System.out.println("    Total timing entries found: " + timings.size());

        } catch (Exception e) {
            System.out.println("    Error processing " + filename + ": " + e.getMessage());
        }

        return timings;
    }

    private static Map<String, PerformanceMetrics> calculatePerformanceMetrics(
            List<TimingInfo> beforeTimings, List<TimingInfo> afterTimings) {

        Map<String, PerformanceMetrics> metrics = new HashMap<>();

        // Process before timings
        for (TimingInfo timing : beforeTimings) {
            String key = timing.category + " - " + timing.operation;
            if (!metrics.containsKey(key)) {
                metrics.put(key, new PerformanceMetrics(key));
            }
            metrics.get(key).beforeTimes.add(timing.timeInMs);
        }

        // Process after timings
        for (TimingInfo timing : afterTimings) {
            String key = timing.category + " - " + timing.operation;
            if (!metrics.containsKey(key)) {
                metrics.put(key, new PerformanceMetrics(key));
            }
            metrics.get(key).afterTimes.add(timing.timeInMs);
        }

        // Calculate weighted averages for all metrics
        for (PerformanceMetrics metric : metrics.values()) {
            metric.calculateWeightedAverages();
        }

        return metrics;
    }

    private static void printTopPerformers(Map<String, PerformanceMetrics> metrics, int count) {
        System.out.println("\n+------------------------------------------------------------------------------+");
        System.out.println("|                          TOP " + count + " BEST PERFORMING METHODS                           |");
        System.out.println("+----------------------------------------------------------------------------+-------------+-------------+-------------+-------------+");
        System.out.println("| Method Name                                                               | Before Avg  | After Avg   | Calls B/A   | Improv(%)   |");
        System.out.println("+----------------------------------------------------------------------------+-------------+-------------+-------------+-------------+");

        // Filter methods that have both before and after data
        List<PerformanceMetrics> validMetrics = metrics.values().stream()
                .filter(m -> !m.beforeTimes.isEmpty() && !m.afterTimes.isEmpty())
                .collect(Collectors.toList());

        // Sort by improvement percentage (highest first)
        validMetrics.sort((a, b) -> Double.compare(b.improvementPercent, a.improvementPercent));

        // Print top performers
        int printed = 0;
        for (PerformanceMetrics metric : validMetrics) {
            if (printed >= count) break;

            // Skip negative improvements for "top performers"
            if (metric.improvementPercent <= 0) continue;

            printMetricRow(metric);
            printed++;
        }

        System.out.println("+----------------------------------------------------------------------------+-------------+-------------+-------------+-------------+");
    }

    private static void printWorstPerformers(Map<String, PerformanceMetrics> metrics, int count) {
        System.out.println("\n+------------------------------------------------------------------------------+");
        System.out.println("|                          TOP " + count + " WORST PERFORMING METHODS                          |");
        System.out.println("+----------------------------------------------------------------------------+-------------+-------------+-------------+-------------+");
        System.out.println("| Method Name                                                               | Before Avg  | After Avg   | Calls B/A   | Improv(%)   |");
        System.out.println("+----------------------------------------------------------------------------+-------------+-------------+-------------+-------------+");

        // Filter methods that have both before and after data
        List<PerformanceMetrics> validMetrics = metrics.values().stream()
                .filter(m -> !m.beforeTimes.isEmpty() && !m.afterTimes.isEmpty())
                .collect(Collectors.toList());

        // Sort by improvement percentage (lowest first)
        validMetrics.sort((a, b) -> Double.compare(a.improvementPercent, b.improvementPercent));

        // Print worst performers
        int printed = 0;
        for (PerformanceMetrics metric : validMetrics) {
            if (printed >= count) break;
            printMetricRow(metric);
            printed++;
        }

        System.out.println("+----------------------------------------------------------------------------+-------------+-------------+-------------+-------------+");
    }

    private static void printMetricRow(PerformanceMetrics metric) {
        String methodName = metric.operation;
        if (methodName.length() > 74) {
            methodName = methodName.substring(0, 71) + "...";
        }

        // Format the row with proper alignment
        System.out.printf("| %-74s | %11.2f | %11.2f | %5d/%-5d | %+11.2f%% |\n",
                methodName,
                metric.weightedBeforeAvg,
                metric.weightedAfterAvg,
                metric.beforeCount,
                metric.afterCount,
                metric.improvementPercent);
    }

    private static void printOverallPerformance(Map<String, PerformanceMetrics> metrics) {
        // Calculate overall weighted averages
        List<Integer> allBeforeTimes = new ArrayList<>();
        List<Integer> allAfterTimes = new ArrayList<>();

        List<Integer> initBeforeTimes = new ArrayList<>();
        List<Integer> initAfterTimes = new ArrayList<>();

        List<Integer> methodBeforeTimes = new ArrayList<>();
        List<Integer> methodAfterTimes = new ArrayList<>();

        for (PerformanceMetrics metric : metrics.values()) {
            if (metric.operation.contains("Initialization")) {
                initBeforeTimes.addAll(metric.beforeTimes);
                initAfterTimes.addAll(metric.afterTimes);
            } else {
                methodBeforeTimes.addAll(metric.beforeTimes);
                methodAfterTimes.addAll(metric.afterTimes);
            }

            allBeforeTimes.addAll(metric.beforeTimes);
            allAfterTimes.addAll(metric.afterTimes);
        }

        PerformanceMetrics overallMetrics = new PerformanceMetrics("OVERALL");
        overallMetrics.beforeTimes = allBeforeTimes;
        overallMetrics.afterTimes = allAfterTimes;
        overallMetrics.calculateWeightedAverages();

        PerformanceMetrics initMetrics = new PerformanceMetrics("INITIALIZATION");
        initMetrics.beforeTimes = initBeforeTimes;
        initMetrics.afterTimes = initAfterTimes;
        initMetrics.calculateWeightedAverages();

        PerformanceMetrics methodMetrics = new PerformanceMetrics("METHOD EXECUTION");
        methodMetrics.beforeTimes = methodBeforeTimes;
        methodMetrics.afterTimes = methodAfterTimes;
        methodMetrics.calculateWeightedAverages();

        System.out.println("\n+------------------------------------------------------------------------------+");
        System.out.println("|                               OVERALL PERFORMANCE SUMMARY                            |");
        System.out.println("+----------------------------------------------------------------------------+-------------+-------------+-------------+-------------+");
        System.out.println("| Category                                                                  | Before Avg  | After Avg   | Calls B/A   | Improv(%)   |");
        System.out.println("+----------------------------------------------------------------------------+-------------+-------------+-------------+-------------+");
        printMetricRow(initMetrics);
        printMetricRow(methodMetrics);
        System.out.println("+----------------------------------------------------------------------------+-------------+-------------+-------------+-------------+");
        printMetricRow(overallMetrics);
        System.out.println("+----------------------------------------------------------------------------+-------------+-------------+-------------+-------------+");

        // Print a note about weighted averages
        System.out.println("\nNOTE: All averages are weighted by frequency of method calls for accurate representation");
        System.out.println("      of real-world usage patterns. Methods called more frequently have greater impact on");
        System.out.println("      the overall performance metrics.");
    }
}

Enter fullscreen mode Exit fullscreen mode

Top comments (0)