Reducer.java

177 lines | 6.856 kB Blame History Raw Download
package br.ufrgs.inf.prosoft.cache.tools;

import br.ufrgs.inf.prosoft.cache.CacheEvent;
import br.ufrgs.inf.prosoft.cache.EventType;
import com.google.gson.Gson;

import java.io.FileWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.*;
import java.util.concurrent.atomic.AtomicLong;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class Reducer {

  private static final Logger LOGGER = Logger.getLogger(Reducer.class.getName());

  public static void reduce(String eventsPath, String reducePath, String prefix) {
    try (Stream<String> lines = Files.lines(Paths.get(eventsPath))) {
      Gson gson = new Gson();
      Map<String, Integer> objectHasHits = new HashMap<>();
      lines.forEach(line -> {
        CacheEvent event = gson.fromJson(line, CacheEvent.class);
        if (event.getType().equals(EventType.HIT) || event.getType().equals(EventType.ADDITION) || event.getType().equals(EventType.MISS)) {
          String identifier = event.getName() + "," + event.getIdentifier() + "," + event.getType().name().toLowerCase();
          try {
            objectHasHits.put(identifier, objectHasHits.get(identifier) + 1);
          } catch (Exception ex) {
            objectHasHits.put(identifier, 1);
          }
        }
      });

      try (FileWriter fileWriter = new FileWriter(reducePath, true)) {
        objectHasHits.forEach((key, value) -> {
          try {
            fileWriter.write(prefix + key + "," + value + "\n");
          } catch (IOException ex) {
            LOGGER.log(Level.SEVERE, "IOException {0}", ex);
          }
        });
      }
    } catch (IOException ex) {
      LOGGER.log(Level.SEVERE, "file not found {0}", eventsPath);
    }
  }

  public static void size(String eventsPath, String reducePath, String prefix) {
    try (Stream<String> lines = Files.lines(Paths.get(eventsPath))) {
      Gson gson = new Gson();
      List<CacheEvent> events = lines
        .map(it -> gson.fromJson(it, CacheEvent.class))
        .sorted(Comparator.comparingLong(CacheEvent::getTime))
        .collect(Collectors.toList());
      long startTime = events.get(0).getTime();
      try (FileWriter fileWriter = new FileWriter(reducePath, true)) {
        AtomicLong currentCacheSize = new AtomicLong();
        fileWriter.write(prefix + events.get(0).getName() + "," + 0 + "," + currentCacheSize + "\n");
        events.forEach(it -> {
          if (it.getType().equals(EventType.ADDITION) || it.getType().equals(EventType.REPLACE)) {
            if ((it.getName().contains(":single-") || it.getName().contains(":getter-")) && currentCacheSize.get() == 1 || it.getType().equals(EventType.REPLACE)) {
              currentCacheSize.getAndDecrement();
              try {
                long adjustedTime = it.getTime() - startTime;
                fileWriter.write(prefix + it.getName() + "," + adjustedTime + "," + currentCacheSize + "\n");
              } catch (IOException ex) {
                LOGGER.log(Level.SEVERE, "output error {0}", reducePath);
              }
            }
            currentCacheSize.getAndIncrement();
          } else if (it.getType().equals(EventType.INVALIDATION)) currentCacheSize.getAndDecrement();
          else return;
          try {
            long adjustedTime = it.getTime() - startTime;
            fileWriter.write(prefix + it.getName() + "," + adjustedTime + "," + currentCacheSize + "\n");
          } catch (IOException ex) {
            LOGGER.log(Level.SEVERE, "output error {0}", reducePath);
          }
        });
        long endTime = events.get(events.size() - 1).getTime() - startTime;
        fileWriter.write(prefix + events.get(events.size() - 1).getName() + "," + endTime + "," + currentCacheSize + "\n");
      } catch (IOException ex) {
        LOGGER.log(Level.SEVERE, "output error {0}", reducePath);
      }
    } catch (IOException ex) {
      LOGGER.log(Level.SEVERE, "output error {0}", eventsPath);
    }
  }

  public static void savedTimeAndTimeInCache(String eventsPath, String recommendedTTLsPath, String averageExecutionsPath, String reducePath, String prefix) {
    CSV recommendedTTLs = CSV.read(recommendedTTLsPath);
    CSV averageExecutions = CSV.read(averageExecutionsPath);

    Map<String, Method> methods = new HashMap<>();

    recommendedTTLs.forEach(row -> {
      String reference = row.get("reference");
      Optional<CSV.Row> selectFirst = averageExecutions.selectFirst("reference", reference);
      if (selectFirst.isPresent()) {
        Method method = new Method();
        method.reference = reference;
        method.ttl = Long.parseLong(row.get("ttl"));
        method.avgexecution = Double.parseDouble(selectFirst.get().get("avgexecution"));
        if (methods.containsKey(reference)) {
          throw new RuntimeException("Trying to overwrite reference " + reference);
        }
        String uuid = row.get("application") + "," + row.get("version") + "," + row.get("group") + "," + row.get("method");
        methods.put(uuid, method);
      }
    });

    String[] splitPrefix = prefix.split(",");
    String application = splitPrefix[0];
    String version = splitPrefix[1];
    String group = splitPrefix[2];

    String uuid = application + "," + version + "," + group + ",";

    try (Stream<String> lines = Files.lines(Paths.get(eventsPath))) {
      Gson gson = new Gson();
      lines.forEach(line -> {
        CacheEvent event = gson.fromJson(line, CacheEvent.class);
        if (event.getType().equals(EventType.HIT) || event.getType().equals(EventType.ADDITION)) {
          Method method = methods.get(uuid + event.getName());
          if (method == null) {
            LOGGER.log(Level.FINE, "Method in events was not recommended {0}{1}", new Object[]{uuid, event.getName()});
            return;
          }
          if (event.getType().equals(EventType.HIT)) {
            method.hits++;
          } else {
            method.additions++;
          }
        }
      });

      try (FileWriter fileWriter = new FileWriter(reducePath, true)) {
        methods.values().forEach(method -> {
          try {
            if (method.hits + method.additions > 0) {
              fileWriter.write(prefix + method.reference + "," + method.avgexecution + "," + method.ttl + "," + method.additions + "," + method.hits + "," + method.getSavedTime() + "," + method.getTimeInCache() + "\n");
            }
          } catch (IOException ex) {
            LOGGER.log(Level.SEVERE, "IOException {0}", ex);
          }
        });
      }
    } catch (IOException ex) {
      LOGGER.log(Level.SEVERE, "file not found {0}", eventsPath);
    }
  }

  private static class Method {

    String name;
    String reference;
    long ttl;
    double avgexecution;
    int hits;
    int additions;

    double getSavedTime() {
      return avgexecution * hits;
    }

    long getTimeInCache() {
      return ttl * additions;
    }

  }

}