Merge "Improve the slow query instrumentation." into ics-mr0
This commit is contained in:
@@ -55,6 +55,7 @@ public class CursorWindow extends SQLiteClosable implements Parcelable {
|
|||||||
public int mWindowPtr;
|
public int mWindowPtr;
|
||||||
|
|
||||||
private int mStartPos;
|
private int mStartPos;
|
||||||
|
private final String mName;
|
||||||
|
|
||||||
private final CloseGuard mCloseGuard = CloseGuard.get();
|
private final CloseGuard mCloseGuard = CloseGuard.get();
|
||||||
|
|
||||||
@@ -85,6 +86,8 @@ public class CursorWindow extends SQLiteClosable implements Parcelable {
|
|||||||
private static native boolean nativePutDouble(int windowPtr, double value, int row, int column);
|
private static native boolean nativePutDouble(int windowPtr, double value, int row, int column);
|
||||||
private static native boolean nativePutNull(int windowPtr, int row, int column);
|
private static native boolean nativePutNull(int windowPtr, int row, int column);
|
||||||
|
|
||||||
|
private static native String nativeGetName(int windowPtr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new empty cursor window and gives it a name.
|
* Creates a new empty cursor window and gives it a name.
|
||||||
* <p>
|
* <p>
|
||||||
@@ -100,6 +103,7 @@ public class CursorWindow extends SQLiteClosable implements Parcelable {
|
|||||||
*/
|
*/
|
||||||
public CursorWindow(String name, boolean localWindow) {
|
public CursorWindow(String name, boolean localWindow) {
|
||||||
mStartPos = 0;
|
mStartPos = 0;
|
||||||
|
mName = name;
|
||||||
mWindowPtr = nativeCreate(name, sCursorWindowSize, localWindow);
|
mWindowPtr = nativeCreate(name, sCursorWindowSize, localWindow);
|
||||||
if (mWindowPtr == 0) {
|
if (mWindowPtr == 0) {
|
||||||
throw new CursorWindowAllocationException("Cursor window allocation of " +
|
throw new CursorWindowAllocationException("Cursor window allocation of " +
|
||||||
@@ -130,6 +134,7 @@ public class CursorWindow extends SQLiteClosable implements Parcelable {
|
|||||||
throw new CursorWindowAllocationException("Cursor window could not be "
|
throw new CursorWindowAllocationException("Cursor window could not be "
|
||||||
+ "created from binder.");
|
+ "created from binder.");
|
||||||
}
|
}
|
||||||
|
mName = nativeGetName(mWindowPtr);
|
||||||
mCloseGuard.open("close");
|
mCloseGuard.open("close");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -156,6 +161,14 @@ public class CursorWindow extends SQLiteClosable implements Parcelable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the name of this cursor window.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public String getName() {
|
||||||
|
return mName;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Closes the cursor window and frees its underlying resources when all other
|
* Closes the cursor window and frees its underlying resources when all other
|
||||||
* remaining references have been released.
|
* remaining references have been released.
|
||||||
@@ -778,4 +791,9 @@ public class CursorWindow extends SQLiteClosable implements Parcelable {
|
|||||||
String s = (buff.length() > 980) ? buff.substring(0, 980) : buff.toString();
|
String s = (buff.length() > 980) ? buff.substring(0, 980) : buff.toString();
|
||||||
return "# Open Cursors=" + total + s;
|
return "# Open Cursors=" + total + s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return getName() + " {" + Integer.toHexString(mWindowPtr) + "}";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -306,10 +306,6 @@ public class SQLiteDatabase extends SQLiteClosable {
|
|||||||
/** Used to find out where this object was created in case it never got closed. */
|
/** Used to find out where this object was created in case it never got closed. */
|
||||||
private final Throwable mStackTrace;
|
private final Throwable mStackTrace;
|
||||||
|
|
||||||
// System property that enables logging of slow queries. Specify the threshold in ms.
|
|
||||||
private static final String LOG_SLOW_QUERIES_PROPERTY = "db.log.slow_query_threshold";
|
|
||||||
private final int mSlowQueryThreshold;
|
|
||||||
|
|
||||||
/** stores the list of statement ids that need to be finalized by sqlite */
|
/** stores the list of statement ids that need to be finalized by sqlite */
|
||||||
private final ArrayList<Integer> mClosedStatementIds = new ArrayList<Integer>();
|
private final ArrayList<Integer> mClosedStatementIds = new ArrayList<Integer>();
|
||||||
|
|
||||||
@@ -1559,11 +1555,6 @@ public class SQLiteDatabase extends SQLiteClosable {
|
|||||||
String editTable) {
|
String editTable) {
|
||||||
verifyDbIsOpen();
|
verifyDbIsOpen();
|
||||||
BlockGuard.getThreadPolicy().onReadFromDisk();
|
BlockGuard.getThreadPolicy().onReadFromDisk();
|
||||||
long timeStart = 0;
|
|
||||||
|
|
||||||
if (false || mSlowQueryThreshold != -1) {
|
|
||||||
timeStart = System.currentTimeMillis();
|
|
||||||
}
|
|
||||||
|
|
||||||
SQLiteDatabase db = getDbConnection(sql);
|
SQLiteDatabase db = getDbConnection(sql);
|
||||||
SQLiteCursorDriver driver = new SQLiteDirectCursorDriver(db, sql, editTable);
|
SQLiteCursorDriver driver = new SQLiteDirectCursorDriver(db, sql, editTable);
|
||||||
@@ -1574,24 +1565,6 @@ public class SQLiteDatabase extends SQLiteClosable {
|
|||||||
cursorFactory != null ? cursorFactory : mFactory,
|
cursorFactory != null ? cursorFactory : mFactory,
|
||||||
selectionArgs);
|
selectionArgs);
|
||||||
} finally {
|
} finally {
|
||||||
if (false || mSlowQueryThreshold != -1) {
|
|
||||||
|
|
||||||
// Force query execution
|
|
||||||
int count = -1;
|
|
||||||
if (cursor != null) {
|
|
||||||
count = cursor.getCount();
|
|
||||||
}
|
|
||||||
|
|
||||||
long duration = System.currentTimeMillis() - timeStart;
|
|
||||||
|
|
||||||
if (false || duration >= mSlowQueryThreshold) {
|
|
||||||
Log.v(SQLiteCursor.TAG,
|
|
||||||
"query (" + duration + " ms): " + driver.toString() + ", args are "
|
|
||||||
+ (selectionArgs != null
|
|
||||||
? TextUtils.join(",", selectionArgs)
|
|
||||||
: "<null>") + ", count is " + count);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
releaseDbConnection(db);
|
releaseDbConnection(db);
|
||||||
}
|
}
|
||||||
return cursor;
|
return cursor;
|
||||||
@@ -1967,7 +1940,6 @@ public class SQLiteDatabase extends SQLiteClosable {
|
|||||||
setMaxSqlCacheSize(DEFAULT_SQL_CACHE_SIZE);
|
setMaxSqlCacheSize(DEFAULT_SQL_CACHE_SIZE);
|
||||||
mFlags = flags;
|
mFlags = flags;
|
||||||
mPath = path;
|
mPath = path;
|
||||||
mSlowQueryThreshold = SystemProperties.getInt(LOG_SLOW_QUERIES_PROPERTY, -1);
|
|
||||||
mStackTrace = new DatabaseObjectNotClosedException().fillInStackTrace();
|
mStackTrace = new DatabaseObjectNotClosedException().fillInStackTrace();
|
||||||
mFactory = factory;
|
mFactory = factory;
|
||||||
mPrograms = new WeakHashMap<SQLiteClosable,Object>();
|
mPrograms = new WeakHashMap<SQLiteClosable,Object>();
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ package android.database.sqlite;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import android.os.Build;
|
||||||
|
import android.os.SystemProperties;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -64,6 +66,28 @@ public final class SQLiteDebug {
|
|||||||
public static final boolean DEBUG_LOCK_TIME_TRACKING_STACK_TRACE =
|
public static final boolean DEBUG_LOCK_TIME_TRACKING_STACK_TRACE =
|
||||||
Log.isLoggable("SQLiteLockStackTrace", Log.VERBOSE);
|
Log.isLoggable("SQLiteLockStackTrace", Log.VERBOSE);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* True to enable database performance testing instrumentation.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public static final boolean DEBUG_LOG_SLOW_QUERIES = Build.IS_DEBUGGABLE;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines whether a query should be logged.
|
||||||
|
*
|
||||||
|
* Reads the "db.log.slow_query_threshold" system property, which can be changed
|
||||||
|
* by the user at any time. If the value is zero, then all queries will
|
||||||
|
* be considered slow. If the value does not exist, then no queries will
|
||||||
|
* be considered slow.
|
||||||
|
*
|
||||||
|
* This value can be changed dynamically while the system is running.
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public static final boolean shouldLogSlowQuery(long elapsedTimeMillis) {
|
||||||
|
int slowQueryMillis = SystemProperties.getInt("db.log.slow_query_threshold", -1);
|
||||||
|
return slowQueryMillis >= 0 && elapsedTimeMillis > slowQueryMillis;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Contains statistics about the active pagers in the current process.
|
* Contains statistics about the active pagers in the current process.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ package android.database.sqlite;
|
|||||||
|
|
||||||
import android.database.CursorWindow;
|
import android.database.CursorWindow;
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -32,6 +33,7 @@ public class SQLiteQuery extends SQLiteProgram {
|
|||||||
|
|
||||||
private static native int nativeFillWindow(int databasePtr, int statementPtr, int windowPtr,
|
private static native int nativeFillWindow(int databasePtr, int statementPtr, int windowPtr,
|
||||||
int startPos, int offsetParam);
|
int startPos, int offsetParam);
|
||||||
|
|
||||||
private static native int nativeColumnCount(int statementPtr);
|
private static native int nativeColumnCount(int statementPtr);
|
||||||
private static native String nativeColumnName(int statementPtr, int columnIndex);
|
private static native String nativeColumnName(int statementPtr, int columnIndex);
|
||||||
|
|
||||||
@@ -80,8 +82,24 @@ public class SQLiteQuery extends SQLiteProgram {
|
|||||||
acquireReference();
|
acquireReference();
|
||||||
try {
|
try {
|
||||||
window.acquireReference();
|
window.acquireReference();
|
||||||
|
int startPos = window.getStartPosition();
|
||||||
int numRows = nativeFillWindow(nHandle, nStatement, window.mWindowPtr,
|
int numRows = nativeFillWindow(nHandle, nStatement, window.mWindowPtr,
|
||||||
window.getStartPosition(), mOffsetIndex);
|
startPos, mOffsetIndex);
|
||||||
|
if (SQLiteDebug.DEBUG_LOG_SLOW_QUERIES) {
|
||||||
|
long elapsed = SystemClock.uptimeMillis() - timeStart;
|
||||||
|
if (SQLiteDebug.shouldLogSlowQuery(elapsed)) {
|
||||||
|
Log.d(TAG, "fillWindow took " + elapsed
|
||||||
|
+ " ms: window=\"" + window
|
||||||
|
+ "\", startPos=" + startPos
|
||||||
|
+ ", offset=" + mOffsetIndex
|
||||||
|
+ ", filledRows=" + window.getNumRows()
|
||||||
|
+ ", countedRows=" + numRows
|
||||||
|
+ ", query=\"" + mSql + "\""
|
||||||
|
+ ", args=[" + (mBindArgs != null ?
|
||||||
|
TextUtils.join(", ", mBindArgs.values()) : "")
|
||||||
|
+ "]");
|
||||||
|
}
|
||||||
|
}
|
||||||
mDatabase.logTimeStat(mSql, timeStart);
|
mDatabase.logTimeStat(mSql, timeStart);
|
||||||
return numRows;
|
return numRows;
|
||||||
} catch (IllegalStateException e){
|
} catch (IllegalStateException e){
|
||||||
|
|||||||
@@ -325,6 +325,13 @@ public class Build {
|
|||||||
public static final String USER = getString("ro.build.user");
|
public static final String USER = getString("ro.build.user");
|
||||||
public static final String HOST = getString("ro.build.host");
|
public static final String HOST = getString("ro.build.host");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true if we are running a debug build such as "user-debug" or "eng".
|
||||||
|
* @hide
|
||||||
|
*/
|
||||||
|
public static final boolean IS_DEBUGGABLE =
|
||||||
|
SystemProperties.getInt("ro.debuggable", 0) == 1;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the version string for the radio firmware. May return
|
* Returns the version string for the radio firmware. May return
|
||||||
* null (if, for instance, the radio is not currently on).
|
* null (if, for instance, the radio is not currently on).
|
||||||
|
|||||||
@@ -104,6 +104,11 @@ static void nativeDispose(JNIEnv* env, jclass clazz, jint windowPtr) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static jstring nativeGetName(JNIEnv* env, jclass clazz, jint windowPtr) {
|
||||||
|
CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr);
|
||||||
|
return env->NewStringUTF(window->name().string());
|
||||||
|
}
|
||||||
|
|
||||||
static void nativeWriteToParcel(JNIEnv * env, jclass clazz, jint windowPtr,
|
static void nativeWriteToParcel(JNIEnv * env, jclass clazz, jint windowPtr,
|
||||||
jobject parcelObj) {
|
jobject parcelObj) {
|
||||||
CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr);
|
CursorWindow* window = reinterpret_cast<CursorWindow*>(windowPtr);
|
||||||
@@ -485,6 +490,8 @@ static JNINativeMethod sMethods[] =
|
|||||||
(void*)nativeDispose },
|
(void*)nativeDispose },
|
||||||
{ "nativeWriteToParcel", "(ILandroid/os/Parcel;)V",
|
{ "nativeWriteToParcel", "(ILandroid/os/Parcel;)V",
|
||||||
(void*)nativeWriteToParcel },
|
(void*)nativeWriteToParcel },
|
||||||
|
{ "nativeGetName", "(I)Ljava/lang/String;",
|
||||||
|
(void*)nativeGetName },
|
||||||
{ "nativeClear", "(I)V",
|
{ "nativeClear", "(I)V",
|
||||||
(void*)nativeClear },
|
(void*)nativeClear },
|
||||||
{ "nativeGetNumRows", "(I)I",
|
{ "nativeGetNumRows", "(I)I",
|
||||||
|
|||||||
@@ -211,7 +211,7 @@ uint32_t CursorWindow::alloc(size_t size, bool aligned) {
|
|||||||
uint32_t offset = mHeader->freeOffset + padding;
|
uint32_t offset = mHeader->freeOffset + padding;
|
||||||
uint32_t nextFreeOffset = offset + size;
|
uint32_t nextFreeOffset = offset + size;
|
||||||
if (nextFreeOffset > mSize) {
|
if (nextFreeOffset > mSize) {
|
||||||
LOGE("Window is full: requested allocation %d bytes, "
|
LOGW("Window is full: requested allocation %d bytes, "
|
||||||
"free space %d bytes, window size %d bytes",
|
"free space %d bytes, window size %d bytes",
|
||||||
size, freeSpace(), mSize);
|
size, freeSpace(), mSize);
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
Reference in New Issue
Block a user