Exemple #1
0
 /**
  * Return a string that describes the statistics for the top n entries, sorted by descending
  * order of total time spent dealing with the query. This will always include the totals entry
  * in the first position.
  *
  * @param n the desired number of entries to describe
  * @return a string describing the statistics for the top n entries
  */
 public synchronized String toStringTop(int n) {
   StringBuilder out = new StringBuilder();
   List<Entry> list = entries();
   if (list.isEmpty()) return "<no queries executed>";
   Collections.sort(list, TOTAL_TIME_DESCENDING);
   int maxCountLength = COUNT_FORMAT.format(list.get(0).numQueries).length();
   double totalDuration = list.get(0).queryTime;
   for (Entry entry : list.subList(0, Math.min(n, list.size())))
     out.append(entry.toString(maxCountLength, totalDuration)).append('\n');
   return out.toString();
 }
Exemple #2
0
 public synchronized String toString(int maxCountLength, double totalDuration) {
   String formattedCount =
       String.format("%" + maxCountLength + "s", COUNT_FORMAT.format(numQueries));
   return FULL_ENTRY_FORMAT.format(
       new Object[] {
         query == null ? "TOTALS" : query,
         formattedCount,
         (queriesPrepared - queriesCompiled) / (double) queriesPrepared,
         queryTime,
         queryCompilationTime,
         queryPreparationTime,
         queryRunTime,
         queryTime * 1000 / numQueries,
         queriesCompiled == 0 ? 0 : queryCompilationTime * 1000 / queriesCompiled,
         queriesPrepared == 0 ? 0 : queryPreparationTime * 1000 / queriesPrepared,
         queriesRun == 0 ? 0 : queryRunTime * 1000 / queriesRun,
         queryTime / totalDuration
       });
 }
Exemple #3
0
  public static class Statistics {
    private static final NumberFormat COUNT_FORMAT = NumberFormat.getIntegerInstance();
    private static final MessageFormat FULL_ENTRY_FORMAT =
        new MessageFormat(
            "{1} uses in {3,number,0.000}s ({11,number,percent}, {7,number,0.00}ms avg) ["
                + "{4,number,0.000}s compiling ({8,number,0.00}ms avg, {2,number,percent} cache hits), "
                + "{5,number,0.000}s preparing ({9,number,0.00}ms avg), {6,number,0.000}s executing ({10,number,0.00}ms avg)"
                + "]: {0}");
    private static final MessageFormat STAND_ALONE_ENTRY_FORMAT =
        new MessageFormat(
            "{1,number,integer} uses in {3,number,0.000}s ({7,number,0.00}ms avg) ["
                + "{4,number,0.000}s compiling ({8,number,0.00}ms avg, {2,number,percent} cache hits), "
                + "{5,number,0.000}s preparing ({9,number,0.00}ms avg), {6,number,0.000}s executing ({10,number,0.00}ms avg)"
                + "]: {0}");

    private static final Comparator<Entry> TOTAL_TIME_DESCENDING =
        new Comparator<Entry>() {
          public int compare(Entry e1, Entry e2) {
            return e1.queryTime == e2.queryTime ? 0 : (e1.queryTime > e2.queryTime ? -1 : 1);
          }
        };

    private final Map<String, Entry> entries = new HashMap<String, Entry>();

    void update(String query, long t1, long t2, long t3, long t4, long t5) {
      long tQuery = t5 - t1,
          tPreparation = t2 > 0 ? t2 - t1 : -1,
          tCompilation = t3 > 0 ? t3 - t2 : -1,
          tExecution = t4 > 0 ? t4 - (t3 > 0 ? t3 : t2) : -1;
      get(null).update(tQuery, tPreparation, tCompilation, tExecution);
      get(query).update(tQuery, tPreparation, tCompilation, tExecution);
    }

    synchronized Entry get(String query) {
      Entry entry = entries.get(query);
      if (entry == null) entries.put(query, entry = new Entry(query));
      return entry;
    }

    /**
     * Get a list of all statistics entries for which data has been gathered. The list is a copy and
     * can be further manipulating without affecting the service.
     *
     * @return a list of all statistics entries
     */
    public synchronized List<Entry> entries() {
      return new ArrayList<Entry>(entries.values());
    }

    /**
     * Get the entry that aggregates statistics over all the queries.
     *
     * @return the totals entry
     */
    public Entry totals() {
      return get(null);
    }

    /** Reset all gathered statistics back to zero. */
    public synchronized void reset() {
      entries.clear();
    }

    /**
     * Return a string that describes the statistics gathered for all the entries.
     *
     * @return a string describing the statistics gathered so far
     */
    public synchronized String toString() {
      return toStringTop(entries.size());
    }

    /**
     * Return a string that describes the statistics for the top n entries, sorted by descending
     * order of total time spent dealing with the query. This will always include the totals entry
     * in the first position.
     *
     * @param n the desired number of entries to describe
     * @return a string describing the statistics for the top n entries
     */
    public synchronized String toStringTop(int n) {
      StringBuilder out = new StringBuilder();
      List<Entry> list = entries();
      if (list.isEmpty()) return "<no queries executed>";
      Collections.sort(list, TOTAL_TIME_DESCENDING);
      int maxCountLength = COUNT_FORMAT.format(list.get(0).numQueries).length();
      double totalDuration = list.get(0).queryTime;
      for (Entry entry : list.subList(0, Math.min(n, list.size())))
        out.append(entry.toString(maxCountLength, totalDuration)).append('\n');
      return out.toString();
    }

    /**
     * Performance counters for a single query. The fields are public for convenience (and to avoid
     * a forest of accessors) but should be considered as read-only.
     *
     * @author <a href="mailto:[email protected]">Piotr Kaminski</a>
     */
    public static class Entry {
      /**
       * The query string (after pre-substitution) that this entry is about. If <code>null</code>
       * then this is the totals entry.
       */
      public final String query;

      // These are simple counters
      public long numQueries, queriesPrepared, queriesCompiled, queriesRun;

      // All times are in seconds.
      public double queryTime, queryPreparationTime, queryCompilationTime, queryRunTime;

      Entry(String query) {
        this.query = query;
      }

      synchronized void update(long tQuery, long tPreparation, long tCompilation, long tRun) {
        numQueries++;
        queryTime += tQuery / 1000.0;
        if (tPreparation >= 0) {
          queriesPrepared++;
          queryPreparationTime += tPreparation / 1000.0;
        }
        if (tCompilation >= 0) {
          queriesCompiled++;
          queryCompilationTime += tCompilation / 1000.0;
        }
        if (tRun >= 0) {
          queryRunTime += tRun / 1000.0;
          queriesRun++;
        }
      }

      public synchronized String toString(int maxCountLength, double totalDuration) {
        String formattedCount =
            String.format("%" + maxCountLength + "s", COUNT_FORMAT.format(numQueries));
        return FULL_ENTRY_FORMAT.format(
            new Object[] {
              query == null ? "TOTALS" : query,
              formattedCount,
              (queriesPrepared - queriesCompiled) / (double) queriesPrepared,
              queryTime,
              queryCompilationTime,
              queryPreparationTime,
              queryRunTime,
              queryTime * 1000 / numQueries,
              queriesCompiled == 0 ? 0 : queryCompilationTime * 1000 / queriesCompiled,
              queriesPrepared == 0 ? 0 : queryPreparationTime * 1000 / queriesPrepared,
              queriesRun == 0 ? 0 : queryRunTime * 1000 / queriesRun,
              queryTime / totalDuration
            });
      }

      @Override
      public synchronized String toString() {
        return STAND_ALONE_ENTRY_FORMAT.format(
            new Object[] {
              query == null ? "TOTALS" : query,
              numQueries,
              (queriesPrepared - queriesCompiled) / (double) queriesPrepared,
              queryTime,
              queryCompilationTime,
              queryPreparationTime,
              queryRunTime,
              queryTime * 1000 / numQueries,
              queriesCompiled == 0 ? 0 : queryCompilationTime * 1000 / queriesCompiled,
              queriesPrepared == 0 ? 0 : queryPreparationTime * 1000 / queriesPrepared,
              queriesRun == 0 ? 0 : queryRunTime * 1000 / queriesRun
            });
      }
    }
  }