/* * Copyright (C) 2017 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License */ package android.database; import android.app.Activity; import android.content.ContentValues; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.os.Bundle; import android.support.test.InstrumentationRegistry; import android.support.test.filters.LargeTest; import android.support.test.runner.AndroidJUnit4; import android.util.ArrayMap; import android.util.Log; import com.android.internal.util.Preconditions; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import java.io.File; import java.io.IOException; import java.nio.file.Files; import java.util.List; import java.util.Map; import static org.junit.Assert.assertEquals; /** * Performance tests for measuring amount of data written during typical DB operations * *
To run: bit CorePerfTests:android.database.SQLiteDatabaseIoPerfTest
*/
@RunWith(AndroidJUnit4.class)
@LargeTest
public class SQLiteDatabaseIoPerfTest {
private static final String TAG = "SQLiteDatabaseIoPerfTest";
private static final String DB_NAME = "db_io_perftest";
private static final int DEFAULT_DATASET_SIZE = 500;
private Long mWriteBytes;
private SQLiteDatabase mDatabase;
private Context mContext;
@Before
public void setUp() {
mContext = InstrumentationRegistry.getTargetContext();
mContext.deleteDatabase(DB_NAME);
mDatabase = mContext.openOrCreateDatabase(DB_NAME, Context.MODE_PRIVATE, null);
mDatabase.execSQL("CREATE TABLE T1 "
+ "(_ID INTEGER PRIMARY KEY, COL_A INTEGER, COL_B VARCHAR(100), COL_C REAL)");
}
@After
public void tearDown() {
mDatabase.close();
mContext.deleteDatabase(DB_NAME);
}
@Test
public void testDatabaseModifications() {
startMeasuringWrites();
ContentValues cv = new ContentValues();
String[] whereArg = new String[1];
for (int i = 0; i < DEFAULT_DATASET_SIZE; i++) {
cv.put("_ID", i);
cv.put("COL_A", i);
cv.put("COL_B", "NewValue");
cv.put("COL_C", 1.0);
assertEquals(i, mDatabase.insert("T1", null, cv));
}
cv = new ContentValues();
for (int i = 0; i < DEFAULT_DATASET_SIZE; i++) {
cv.put("COL_B", "UpdatedValue");
cv.put("COL_C", 1.1);
whereArg[0] = String.valueOf(i);
assertEquals(1, mDatabase.update("T1", cv, "_ID=?", whereArg));
}
for (int i = 0; i < DEFAULT_DATASET_SIZE; i++) {
whereArg[0] = String.valueOf(i);
assertEquals(1, mDatabase.delete("T1", "_ID=?", whereArg));
}
// Make sure all changes are written to disk
mDatabase.close();
long bytes = endMeasuringWrites();
sendResults("testDatabaseModifications" , bytes);
}
@Test
public void testInsertsWithTransactions() {
startMeasuringWrites();
final int txSize = 10;
ContentValues cv = new ContentValues();
for (int i = 0; i < DEFAULT_DATASET_SIZE * 5; i++) {
if (i % txSize == 0) {
mDatabase.beginTransaction();
}
if (i % txSize == txSize-1) {
mDatabase.setTransactionSuccessful();
mDatabase.endTransaction();
}
cv.put("_ID", i);
cv.put("COL_A", i);
cv.put("COL_B", "NewValue");
cv.put("COL_C", 1.0);
assertEquals(i, mDatabase.insert("T1", null, cv));
}
// Make sure all changes are written to disk
mDatabase.close();
long bytes = endMeasuringWrites();
sendResults("testInsertsWithTransactions" , bytes);
}
private void startMeasuringWrites() {
Preconditions.checkState(mWriteBytes == null, "Measurement already started");
mWriteBytes = getIoStats().get("write_bytes");
}
private long endMeasuringWrites() {
Preconditions.checkState(mWriteBytes != null, "Measurement wasn't started");
Long newWriteBytes = getIoStats().get("write_bytes");
return newWriteBytes - mWriteBytes;
}
private void sendResults(String testName, long writeBytes) {
Log.i(TAG, testName + " write_bytes: " + writeBytes);
Bundle status = new Bundle();
status.putLong("write_bytes", writeBytes);
InstrumentationRegistry.getInstrumentation().sendStatus(Activity.RESULT_OK, status);
}
private static Map