Doing some performance optimizations and considering running some tasks in parallel.
Specifically thinking some DB & network operations as they should not bottleneck each other.
The only thing I'm worried is if this will cause problems on lower end devices, still lots of single core phones around. The app has minSDK=10.
For each question please consider it in context of device compatibility:
Can independent Db & Network calls be ran in parallel without problems ?
Does it make sense to consider parallel read-only DB calls ?
Does it make sense to run Network tasks in parallel ?
Any conventions around how many threads should run in parallel ?
Thanks.
DB calls:
- usually databases do not give away 100% of the resources to one call, so yes, multiple calls might help, especially if one request takes the longer time to process in database, but the data are small, anything longer than 100ms,
in the case where the amount of data is big and processing the request in DB is short, then access in multiple calls and limited network speed could lead into issues, like timing etc,
you have to take into consideration if on given device the bottleneck would not be network speed or the customer with limited network etc.
network calls:
I would suggest that the criteria would be very same as with DB calls, lets say it can not be a shocker as DB calls are network calls:).
parallel read only calls to db:
yes, I know cases where it can be fruitful, but I would say for most cases on small devices, it would be too much hassle that could work only in few specific situations, so in general, I would not recommend that,
number of threads, that is device and app
specific question based on:
saving power is priority,
data throughput or latency is priority,
fast computed results from data is priority,
etc.
Related
I have phone with Snapdragon 632 Mobile Platform and some random Android app which shows what your phone has inside (RAM, SoC, sensors, screen density etc.) shows it has 8 cores.
What does it mean from Android app developer perspective?
So I can start (theoretically) up to 8 independent processes which can do work in parallel? Or this has to do with Java's Thread? Or none, find something else to study :) ?
Q : ...up to 8 independent processes which can do work in parallel?
Well, no.A process-based true-[PARALLEL] execution is way more complex, than a just-[CONCURRENT] orchestration of processes ( well known for every serious multitasking / multiprocessing O/S designer ).
Q : What does it mean from Android app developer perspective?
The SoC's 1.8 [GHz] 8-core CPU, reported by your system, is just a one class of resources the O/S has to coordinate all processes' work among - RAM being the next, storage, RTC-device(s), a (global) source of randomness, light-sensor, gyro-sensor(s), etc.
All this sharing-of-resources is a sign of a just-[CONCURRENT] orchestration of processes, where opportunistic scheduling permits a Process to go forward, once some requested resource ( CPU-core, RAM, storage, ... ) gets free to use and scheduler permits a next one waiting to make a small part of it's work and releasing and returning all such resources back, once either a time-quota expires, a signal-request arrives or some async awaiting makes such process to have to wait for some external, independently timed event ( yes, operations across a network are typical case of this ) or was ordered to go and sleep (so, why to block others who need not wait ... and can work during that time or "sleep" ).
O/S may further restrict processes, to become able to use but some of the CPU-cores - this way, such planning may show up, that a physically 8-core CPU might get reported as but a 6-core CPU from some processes, while the other 2-cores were affinity-mapped so that no user-level process will ever touch 'em, so these remain, under any circumstances, free/ready to serve the background processes, not interfering with other, user-level processing bottlenecks, that may happen on the remaining, less restricted 6-cores, where both system-level and user-level processes may get scheduled for execution to take place there.
On a processor level, further details matter. Some CPU-s have SIMD-instructions, that can process many-data, if properly pre-aligned into SIMD-registers, in one and single CPU-instruction step. On the contrary, some 8+ core CPU-s have to share but 2 physical FMA-uop units that can multiply-add, spending but a pair of CPU-CLK-cycles. So if all 8+ cores ask for this very same uOP-instruction, well, "Houston, we have a small problem here ..." - CPU-design thus CISC-CPUs have introduced ( RISC-s have completely different philosophy to avoid getting into this ) a superscalar pipelining with out-of-order instruction re-ordering, so 2-FMA-s process each step but a pair of such pack of 8-requested FMA-uops, interleaving these, on a CPU-uops level, with other ( legally re-ordered instructions ) work. Here you can see, that a deeper Level-of-Detail can surprise during execution, so HPC and hard-RealTime system designers have to pay attention to even this LoD ordering, if System-under-Test has to prove it's ultimate robustness for field-deployment.
Threads are in principle way lighter, than a fully-fledged O/S Process, so way easier to put/release from CPU-core ( cf. a context-switching ), so these are typically used for in-process [CONCURRENT] code-execution ( threads typically share the O/S delivered quota of CPU-time-sharing - i.e. when many O/S Processes inside your O/S's scheduler's queue wait for their time to execute on shared-CPU (cores), all their respective threads wait either ( no sign of thread independence from it's mother Process ). A similar scheduling logic applies to cases, when an 8-core CPU ought execute 888-threads, spawned from a single O/S Process, all that among other 999-system-processes, all waiting in a scheduler queue for their turn ) Also the memory-management is way easier for threads, as they "share" the same address-space, inherited from their mother-Process and can freely access but that address-space, under a homogeneous memory-access policy (and restrictions - will not crash other O/S Processes, yet may devastate their own one's memory state... see Thread-safe-ness issues )
Q : ...something else to study :) ?
The best place to learn from masters is to dive into the O/S design practices - best engineering comes from Real-Time systems, yet it depends a lot on your level of endurance and experience, how easy or hard that will be for you to follow and learn from.
Non-blocking, independent processes can work in a true-[PARALLEL] fashion, given no resources' blocking appears and results are deterministic in TimeDOMAIN -- all start + all execute + all finish -- at the same time. Like an orchestra performing a piece from W.A.Mozart.
If a just-[CONCURRENT] orchestration were permitted for the same piece of music, the violins might start only after they were able to borrow some or all fiddlesticks from viola-players, who might have been waiting in the concert-hall basement, as there was yet not their turn to even get into the dressing-room, piano soloist was still blocked downtown, in the traffic jam and will not be able to finish her part of the Concerto Grosso in about next 3 hours, while bass-players have superfast fiddled all their notes, as nobody was in a need of their super-long fiddle-sticks and they are almost ready to leave the concert-hall and move to playing on another "party" in the neighbouring city, as their boss promised there...
Yes, this would be a just-[CONCURRENT] orchestration, where the resulting "performance" always depends on many local-[ states, parameters ] and also heavily on externalities-( availability of taxi, actual traffic jam and its dynamics, situations like some resource {under|over}-booking )
All that makes a just-[CONCURRENT] execution way simpler in execution ( no strict coordination of resources needed - a "best-effort" - a "Do, if and when someone can" typically suffice ), but in-deterministic in results' ordering.
Wolfgang Amadeus Mozart was definitely designing his pieces of art in a true-[PARALLEL] fashion of how to orchestrate its performance - this is why we all love Amadeus and no one will ever dream to let it be executed in a just-[CONCURRENT] manner :o) no one will ever detect, the today's product of in-deterministically performed piece was the same as was performed, under different external set of external and other conditions, last night or last week, so no one could say if it was Mozart's piece or not at all ... God bless true-[PARALLEL] orchestration never permits to devastate such lovely pieces of art & performs the very way that every time the same result is (almost guaranteed to be) produced...
In my Android app, I have a local DB (SQLite) that the app needs to query for data. The query may take a long time (>5 seconds) so I am avoiding using the main UI thread for that. The returned data may also be rather large (> 1 MB).
Between AsyncTasks, Threads, ExecutorService, and IntentService, (and maybe more) what's the best class/API to use in Android to do this? Are they all more or less the same in terms of what they offer? Or is there a clear winner and a better suited class for database access?
The answer, I'm sure you can predict, is "it depends".
If you are writing a set of related calls (for example that will sync your database using an API), then I would want to use an IntentService since it's a long running operation not directly tied to your user interface.
If it's a one-time operation hitting the database to get a result set, I would lean towards the loader framework/CursorLoader to fetch data for your UI. AsyncTask is an option, although it's really a more general purpose threading mechanism. Also, consider an ORM framework that does threading work or maintains a queue of work items for you.
I can't really think of a case where managing a Thread directly would be the best option. It's very low level and lots of room for error when there are nicer abstractions over it.
According to EventBus doc, there are 4 types of thread modes which EventBus uses to deliver threads:
onEvent()
PostThread
Good for simple tasks
onEventMainThread()
MainThread
a.k.a. UI Thread
Good for UI changes
onEventBackgroundThread()
BackgroundTread
Using single thread, delivering events sequentially.
Good for execution requiring moderate amount of time.
onEventAsync()
Async
Using separate threads.
Good for execution requiring longer time
Question
What are some criteria I should examine before I use onEventBackgroundThread() over onEventAsync(), or vice versa? What would be some examples of using one over the other with obvious advantages?
Which thread modes should each of the following functions use?
Getting the device status -- GPS location of the device (i.e. android.location), Internet connectivity status (i.e. ConnectivityManager, NetworkInfo).
Making simple HTTP requests to receive text (e.g. JSON), taking anywhere between 1000ms to 5000ms, average 2000ms.
Making simple HTTP requests to load images with file sizes between 50kb to 1500kb (exact sizes are unknown to client, before making requests to server).
Caching data to internal database (e.g. SharedPreferences, SQLite, etc).
What are some criteria I should examine before I use onEventBackgroundThread() over onEventAsync(), or vice versa? What would be some examples of using one over the other with obvious advantages?
Well, it's pretty much as the bullets outline. If you don't mind queued, one-at-a-time processing (or perhaps you want it for simpler thread safety), use onEventBackgroundThread(). If you need to do several of them in parallel, particularly if they are I/O-bound, you'd use onEventAsync().
Which thread modes should each of the following functions use?
GPS location of the device (i.e. android.location)
None of the above. LocationManager and the fused location API have their own asynchronous options; I'd use those. Once you get the location handed to you, you could post an event with the location data, but then the threading is dictated by the subscribers to that event, not the poster.
Internet connectivity status (i.e. ConnectivityManager, NetworkInfo)
None of the above, as AFAIK getNetworkInfo() is not an expensive call.
Making simple HTTP requests to receive text (e.g. JSON), taking anywhere between 1000ms to 5000ms, average 2000ms.
None of the above. I'd use Retrofit or another HTTP client library that offers asynchronous options. If for some reason you absolutely have to do the HTTP I/O yourself, it would depend on how frequently this was happening. If, for example, you might fall behind because you fire off several of these in rapid succession, use onEventAsync() so they can run in parallel.
Making simple HTTP requests to load images with file sizes between 50kb to 1500kb (exact sizes are unknown to client, before making requests to server).
None of the above. Use Picasso, Universal Image Loader, or any of the other image-loading libraries, as they all have asynchronous options, and you really need those anyway for the image processing logic. If for some reason you absolutely have to do the HTTP I/O yourself, it'd follow the same rules as I described for the previous item.
Caching data to internal database (e.g. SharedPreferences, SQLite, etc).
Assuming that you're not using some wrapper library here that might offer asynchronous operation, this probably can be handled via onEventBackgroundThread(). That would also give you the advantage of ensuring serialized operation.
I have an SQLite database, which receives some heavy use in my app. It is accessed from:
Various activities, to load data into the UI via ASyncTasks (select statements only)
Several background processes (only one of which can run at a time), which do many inserts/updates
I call getWritableDatabase() once and use this everywhere. Each of the background processes uses an IMMEDIATE (i.e. non-locking) transaction, which speeds some of them up from minutes to seconds.
This all worked perfectly pre-Jellybean; the background processes had the speed benefit of the transaction, but this did not block Activites from loading data via ASyncTasks.
Post-Jellybean, each ASyncTask loading data for the GUI is blocked while a transaction is in progress, so often does not return for several seconds. This makes navigation slow and frustrating. I've isolated the blocking to the rawQuery database call.
I can't find any documentation which specifies exactly what changed in Jellybean, other than several methods being deprecated - http://developer.android.com/reference/android/database/sqlite/SQLiteDatabase.html#isDbLockedByOtherThreads() - with comments like "There is no longer the concept of a database lock, so this method always returns false."
Is there a simple way to mimic the pre-Jellybean behaviour?
It seems that pre-Jelly Bean async tasks were running in parallel all of the time. Now you've got an Executor under the covers running async tasks serially. Good news is, you can specify how your tasks run by branching based on OS version.
Read this article
I've found the solution to my own question. I'm still not sure exactly what Google have changed in Jellybean to stop what worked before working now - but the solution is to use enableWriteAheadLogging().
I had tried this before, to no avail - I was still getting blocked reads while a transaction was in progress. The important bit for me was (in the enableWriteAheadLogging() documentation)
If the database has any attached databases, then execution of queries in parallel is NOT possible.
Unfortunately, my application has two separate databases which are attached together to allow joined queries - enableWriteAheadLogging() returns false. I have prototyped removing the attachment, and this resolves the blocking issue; my select queries all run without delay while another thread runs an IMMEDATE transaction.
Sadly, I'll have to redesign my database schemas to implement a full fix.
I've just recently started working with the android framework and am looking for advice/design patterns to use for the following situation:
Application is a server/client structure. The server should be running at all times (or at least be recreated shortly after termination), but the client can close as need be. To accomplish the server, I understand that I want to extend Service and use START_STICKY functionality and run it in the background.
The part where I'm a bit lost of how to proceed is that I want to create several persistent network connections inside the server. It is important that the connections are threaded and can run asynchronously. A lot of documents point towards using AsyncTask for this, but I don't need to reference the UI thread at all from the network threads and the connections wont ever be terminated, so I'm hoping someone could point me in a better direction?
My conceptual idea was to have the network threads bind to the service to store events, and the client can then also bind to the service to retrieve the events. I'm unsure of the structure to use for these network threads.
The server should be running at all times
There are very very few applications that need this. Statistically speaking, yours probably isn't one of them. Users attack people like you with task killers and the like, plus give out one-star ratings on the Market for harming their use of their device. I strongly encourage you to reconsider this design decision.
so I'm hoping someone could point me in a better direction?
Plain old ordinary Java threads are just fine. Depending on the nature of the threads, you might consider using a thread pool. This part is not significantly different than in other Java environments. Bear in mind that the vast majority of Android devices today are single-core, and you only have so much heap space (as little as 16MB), so having tons o' threads isn't exactly great.
My conceptual idea was to have the network threads bind to the service to store events
The network threads are part of the service, and therefore don't need to bind to it.