📄 profiledconnection.java
字号:
/** * $RCSfile$ * $Revision: 1113 $ * $Date: 2005-03-10 09:53:39 -0800 (Thu, 10 Mar 2005) $ * * Copyright (C) 2004 Jive Software. All rights reserved. * * This software is published under the terms of the GNU Public License (GPL), * a copy of which is included in this distribution. */package org.jivesoftware.database;import java.sql.*;import java.util.Enumeration;import java.util.Hashtable;/** * Wraps a Connection object and collects statistics about the database queries * that are performed.<p> * <p/> * Statistics of the profiled Connections can be obtained from the static * methods of this class. Instances of this class are the actual wrappers that * perform profiling. * * @author Jive Software */public class ProfiledConnection extends AbstractConnection { /** * Constant for SELECT database queries. */ public static final int SELECT = 0; /** * Constant for UPDATE database queries. */ public static final int UPDATE = 1; /** * Constant for INSERT database queries. */ public static final int INSERT = 2; /** * Constant for DELETE database queries. */ public static final int DELETE = 3; private static long startInsertTime = 0; private static long startUpdateTime = 0; private static long startSelectTime = 0; private static long startDeleteTime = 0; private static long endInsertTime = 0; private static long endUpdateTime = 0; private static long endSelectTime = 0; private static long endDeleteTime = 0; private static long insertCount = 0; private static long updateCount = 0; private static long selectCount = 0; private static long deleteCount = 0; private static long totalInsertTime = 0; private static long totalUpdateTime = 0; private static long totalSelectTime = 0; private static long totalDeleteTime = 0; private static Hashtable insertQueries = new Hashtable(); private static Hashtable updateQueries = new Hashtable(); private static Hashtable selectQueries = new Hashtable(); private static Hashtable deleteQueries = new Hashtable(); /** * Start profiling. */ public static void start() { long now = System.currentTimeMillis(); startInsertTime = startUpdateTime = startSelectTime = startDeleteTime = now; } /** * Stop profiling. */ public static void stop() { endInsertTime = endUpdateTime = endSelectTime = endDeleteTime = 0; } /** * Returns the total number database queries of a particular type performed. * Valid types are ProfiledConnection.SELECT, ProfiledConnection.UPDATE, * ProfiledConnection.INSERT, and ProfiledConnection.DELETE. * * @param type the type of query to get the count for. * @return the number queries of type <tt>type</tt> performed. */ public static long getQueryCount(int type) { switch (type) { case SELECT: return selectCount; case UPDATE: return updateCount; case INSERT: return insertCount; case DELETE: return deleteCount; default: throw new IllegalArgumentException("Invalid type"); } } /** * @param sql the insert sql string. * @param time the length of time the query took in milliseconds */ public static void addQuery(int type, String sql, long time) { // Do nothing if we didn't receive a sql statement if (sql == null || sql.equals("")) { return; } // clean up sql to insert spaces after every ',' sql = reformatQuery(sql); // remove values from query sql = removeQueryValues(sql); ProfiledConnectionEntry entry = null; switch (type) { case SELECT: selectCount++; totalSelectTime += time; entry = (ProfiledConnectionEntry)selectQueries.get(sql); if (entry == null) { entry = new ProfiledConnectionEntry(sql); selectQueries.put(sql, entry); } break; case UPDATE: updateCount++; totalUpdateTime += time; entry = (ProfiledConnectionEntry)updateQueries.get(sql); if (entry == null) { entry = new ProfiledConnectionEntry(sql); updateQueries.put(sql, entry); } break; case INSERT: insertCount++; totalInsertTime += time; entry = (ProfiledConnectionEntry)insertQueries.get(sql); if (entry == null) { entry = new ProfiledConnectionEntry(sql); insertQueries.put(sql, entry); } break; case DELETE: deleteCount++; totalDeleteTime += time; entry = (ProfiledConnectionEntry)deleteQueries.get(sql); if (entry == null) { entry = new ProfiledConnectionEntry(sql); deleteQueries.put(sql, entry); } break; default: throw new IllegalArgumentException("Invalid type"); } entry.count++; entry.totalTime += time; } /** * Returns the average number of queries of a certain type that have been * performed per second since profiling started. If profiling has been * stopped, that moment in time is used for the calculation. Otherwise, * the current moment in time is used. * * @param type the type of database query to check. * @return the average number of queries of a certain typed performed per * second. */ public static double getQueriesPerSecond(int type) { long count, start, end; switch (type) { case SELECT: count = selectCount; start = startSelectTime; end = endSelectTime; break; case UPDATE: count = updateCount; start = startUpdateTime; end = endUpdateTime; break; case INSERT: count = insertCount; start = startInsertTime; end = endInsertTime; break; case DELETE: count = deleteCount; start = startDeleteTime; end = endDeleteTime; break; default: throw new IllegalArgumentException("Invalid type"); } // if no queries yet, return 0; if (count == 0) { return 0; } // If the profiling hasn't been stopped yet, we want to give // profiling values up to the current time instead. if (end == 0) { end = System.currentTimeMillis(); } // Compute the number of seconds double time = (end - start) / 1000.0; // Finally, return the average. return count / time; } /** * Returns the average amount of time spent executing the specified type * of query. * * @param type the type of query. * @return a double representing the average time spent executing the type * of query. */ public static double getAverageQueryTime(int type) { long time, count; switch (type) { case SELECT: count = selectCount; time = totalSelectTime; break; case UPDATE: count = updateCount; time = totalUpdateTime; break; case INSERT: count = insertCount; time = totalInsertTime; break; case DELETE: count = deleteCount; time = totalDeleteTime; break; default: throw new IllegalArgumentException("Invalid type"); } if (count != 0) { return time / (double)count; } else { return 0.0; } } /** * Returns the total amount of time in milliseconds spent doing a particular * type of query. Note that this isn't necessarily representative of actual real * time since db queries often occur in parallel. * * @param type the type of query to check. * @return the number of milliseconds spent executing the specified type of * query. */ public static long getTotalQueryTime(int type) { switch (type) { case SELECT: return totalSelectTime; case UPDATE: return totalUpdateTime; case INSERT: return totalInsertTime; case DELETE: return totalDeleteTime; default: throw new IllegalArgumentException("Invalid type"); } } /** * Returns an array of sorted queries (as ProfiledConnectionEntry objects) by type * * @param type the type of query to check * @param sortByTime sort the resulting list by Time if true, * otherwise sort by count if false (default) * @return an array of ProfiledConnectionEntry objects */ public static ProfiledConnectionEntry[] getSortedQueries(int type, boolean sortByTime) { Hashtable queries; switch (type) { case SELECT: queries = selectQueries; break; case UPDATE: queries = updateQueries; break; case INSERT: queries = insertQueries; break; case DELETE: queries = deleteQueries; break; default: throw new IllegalArgumentException("Invalid type"); } ProfiledConnectionEntry[] result = new ProfiledConnectionEntry[queries.size()]; // no queries, return null set if (queries.size() < 1) { return null; } // since the values of the hashtable contain everything that // we need (including the sql statement), ignore the keys Enumeration e = queries.elements(); int c = 0; while (e.hasMoreElements()) { result[c++] = (ProfiledConnectionEntry)e.nextElement(); } quickSort(result, sortByTime, 0, result.length - 1); return result; } /** * Reset all statistics. */ public static void resetStatistics() { startInsertTime = startUpdateTime = startSelectTime = startDeleteTime = 0; endInsertTime = endUpdateTime = endSelectTime = endDeleteTime = 0; insertCount = updateCount = selectCount = deleteCount = 0; totalInsertTime = totalUpdateTime = totalSelectTime = totalDeleteTime = 0; insertQueries.clear(); updateQueries.clear(); selectQueries.clear(); deleteQueries.clear(); } /** * @param entries entries * @param sortByTime sort by time if true, otherwise sort by count * @param first first index to sort on. Normally 0 * @param last last index to sort on. Normally length -1 */ private static void quickSort(ProfiledConnectionEntry[] entries, boolean sortByTime, int first, int last) { // do nothing if array contains fewer than two elements if (first >= last || entries.length < 2) { return; } swap(entries, first, (first + last) / 2); int index = first; for (int i = first + 1; i <= last; i++) { if (sortByTime && ((entries[first].totalTime / entries[first].count) < (entries[i].totalTime / entries[i].count))) { swap(entries, ++index, i); } else if (!sortByTime && entries[first].count < entries[i].count) { swap(entries, ++index, i);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -