Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

initialize performs blocking disk operations on the calling thread. #101

Closed
ajalt opened this issue Apr 21, 2016 · 9 comments
Closed

initialize performs blocking disk operations on the calling thread. #101

ajalt opened this issue Apr 21, 2016 · 9 comments

Comments

@ajalt
Copy link

ajalt commented Apr 21, 2016

The docs recommend calling Amplitude.getInstance().initialize(...) in an onCreate method. However, there are a number or database queries that take place in that call which block the thread they're called on. This has a noticeable impact on application start time.

Here are a couple of the StrictMode reports:

StrictMode policy violation; ~duration=262 ms: android.os.StrictMode$StrictModeDiskWriteViolation: policy=29 violation=1
    at android.os.StrictMode$AndroidBlockGuardPolicy.onWriteToDisk(StrictMode.java:1111)
    at android.database.sqlite.SQLiteConnection.applyBlockGuardPolicy(SQLiteConnection.java:1247)
    at android.database.sqlite.SQLiteConnection.executeForString(SQLiteConnection.java:808)
    at android.database.sqlite.SQLiteConnection.setJournalMode(SQLiteConnection.java:490)
    at android.database.sqlite.SQLiteConnection.setWalModeFromConfiguration(SQLiteConnection.java:464)
    at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:363)
    at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:228)
    at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:512)
    at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:206)
    at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:178)
    at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:908)
    at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:878)
    at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:699)
    at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:1585)
    at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:283)
    at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:223)
    at android.database.sqlite.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:187)
    at com.amplitude.api.DatabaseHelper.getValueFromTable(DatabaseHelper.java:207)
    at com.amplitude.api.DatabaseHelper.getValue(DatabaseHelper.java:196)
    at com.amplitude.api.AmplitudeClient.initialize(AmplitudeClient.java:128)
    at com.amplitude.api.AmplitudeClient.initialize(AmplitudeClient.java:101)


StrictMode policy violation; ~duration=268 ms: android.os.StrictMode$StrictModeDiskWriteViolation: policy=29 violation=1
    at android.os.StrictMode$AndroidBlockGuardPolicy.onWriteToDisk(StrictMode.java:1111)
    at android.database.sqlite.SQLiteConnection.applyBlockGuardPolicy(SQLiteConnection.java:1247)
    at android.database.sqlite.SQLiteConnection.executeForString(SQLiteConnection.java:808)
    at android.database.sqlite.SQLiteConnection.setJournalMode(SQLiteConnection.java:493)
    at android.database.sqlite.SQLiteConnection.setWalModeFromConfiguration(SQLiteConnection.java:464)
    at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:363)
    at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:228)
    at android.database.sqlite.SQLiteConnectionPool.openConnectionLocked(SQLiteConnectionPool.java:512)
    at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:206)
    at android.database.sqlite.SQLiteConnectionPool.open(SQLiteConnectionPool.java:178)
    at android.database.sqlite.SQLiteDatabase.openInner(SQLiteDatabase.java:908)
    at android.database.sqlite.SQLiteDatabase.open(SQLiteDatabase.java:878)
    at android.database.sqlite.SQLiteDatabase.openDatabase(SQLiteDatabase.java:699)
    at android.app.ContextImpl.openOrCreateDatabase(ContextImpl.java:1585)
    at android.content.ContextWrapper.openOrCreateDatabase(ContextWrapper.java:283)
    at android.database.sqlite.SQLiteOpenHelper.getDatabaseLocked(SQLiteOpenHelper.java:223)
    at android.database.sqlite.SQLiteOpenHelper.getReadableDatabase(SQLiteOpenHelper.java:187)
    at com.amplitude.api.DatabaseHelper.getValueFromTable(DatabaseHelper.java:207)
    at com.amplitude.api.DatabaseHelper.getLongValue(DatabaseHelper.java:200)
    at com.amplitude.api.AmplitudeClient.upgradeSharedPrefsToDB(AmplitudeClient.java:1239)
    at com.amplitude.api.AmplitudeClient.upgradeSharedPrefsToDB(AmplitudeClient.java:1227)
    at com.amplitude.api.AmplitudeClient.initialize(AmplitudeClient.java:111)
    at com.amplitude.api.AmplitudeClient.initialize(AmplitudeClient.java:101)

Is it possible for the SDK to perform these calls on a background thread?

@botmane
Copy link

botmane commented Jun 16, 2016

We are having the same problem, due to the SDK, our Android app is launched with a long delay (from +3 s to + 12 s).

We hope that this issue will be resolved as soon as possible.

@djih
Copy link
Member

djih commented Jun 16, 2016

@ajalt @botmane I think the issue is caused by the initial creation of the sqlite database. We timed the init call ourselves, the first time the app opened it was longer than the other times, but no where near 12 s (it was still under 1 s). Subsequent app opening, it only took on avg 50-100ms.

I am exploring putting the logic on a background thread. There is 1 issue, which is the database is required in order to resolve the device Id. Having the initialization logic run asynchronously on a background thread creates cases where getDeviceId() may return null. There are no guarantees that the value will be available when you call the function

@ajalt
Copy link
Author

ajalt commented Jun 16, 2016

My benchmarks show that the Amplitude initialization takes 200ms-500ms on normal app start (after initial creation). That's not 12 seconds, but it is still longer than any other component in our startup procedure.

@botmane
Copy link

botmane commented Jun 22, 2016

Thank you for the reply,

@djih Please find attached 2 videos of our app, one without Amplitude SDK and one with it. videos_amplitude.zip. The phone used is an Asus Zenphone 2 551ML.

This is a very serious matter for us. I hope you can do something about it soon.

Otmane

@djih
Copy link
Member

djih commented Jun 22, 2016

@botmane I am working on a fix now, expect to get it out by end of week

@djih
Copy link
Member

djih commented Jun 27, 2016

@ajalt @botmane apologies for the delay. We have a test branch out with a fix: #109. You can download the compiled jars here:

Please install from the jar file and let us know if that resolves the issue. Thanks!

@ajalt
Copy link
Author

ajalt commented Jun 30, 2016

I tested with the fix. I can't speak about any side effects of moving the initialization to the background thread, but it did fix the main thread stall and the associated StrictMode violations.

@djih
Copy link
Member

djih commented Jun 30, 2016

@ajalt thanks for the update! I'm going to merge it in today and release a new version

@djih
Copy link
Member

djih commented Jun 30, 2016

@ajalt @botmane the fix is pushed with v2.8.0, it should be available on maven within a few hours

@djih djih closed this as completed Jun 30, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants