How can I improve the ActivityManager loading time of my app? - java

I've written an app which processes a lot of data on startup; first startup time of the app is rather slow, but so are subsequent launches.
I previously thought that the relatively un-responsive startup times (~7 seconds) were due to data processing on first load - a bit of debugging suggested about 2 seconds to cold-load. So I redesigned my data structures so they're easier to serialize to persistent storage in between launches (so it caches stuff) and it now saves state when the app finishes in about 20ms, and loading time is about 10-20ms. Much better. (p.s. it's not using the built-in Java serialization, as the state files are now so simple it's easier to save in a plain, human-readable (and editable) text file - it's still pretty quick at reloading from this though!)
However, I'm still finding that the app startup time is about 5 seconds - I've looked in aLogCat which has an entry:
I/ActivityManager(...) blah blah blah: +5s193ms
So more than 5 seconds to load a relatively simple layout (a few nested LinearLayouts, and a few TextViews - nothing special, and no images) - admittedly that time goes down with subsequent launches (I close the app and open it again, it's ~700ms; rinse and repeat for similar results).
Soooo my question is: how can I improve the app loading times? I'm happy that first load takes a little while to process everything - that's fine. But is there a way I can keep the thing in memory, or at least get it into a restorable state so whatever ActivityManager is doing doesn't take so long? I'd like it to be something I can open (probably bound to long-hold search or similar), do whatever, and close it again - thus it needs to open quickly!
Thanks in advance :)
Seb

Run your heavy-duty start-up work in a background thread that you launch in onCreate. (An AsyncTask is good for this.) Design your UI to show something meaningful (at least an indeterminate progress bar) when there is no data. When the data is loaded, post a Runnable (or implement onPostExecute in your AsyncTask) to update the UI to the real thing.

As Ted suggests, do only the minimum on the UI thread. Five seconds to load the layout is too much, which means that there is some start up method that requires a long time (maybe querying databases, or accessing the net, to populate a long ListView?).
If that processing is absolutely required, then use a splash screen (with a "Please wait while loading data" or similar label).

Divide the work using Asyntasks classes. If you have some data which is always the same store it in database for example to have quickest access next time you open the application, and update that content from time to time.

Related

How to handle transactions in Async calls

Due to the slowness of the application, we made some of our long running queries asynchronous. Problem is these are part of a single transaction but in case if these queries/routines fail I need to roll back everything. How to achieve this? This application is legacy application using JDBC oracle and java 8. Also like to know if there is any support for this in Springboot, jpa application.
Thanks in advance.
Don't try to interact with the same DB connection from multiple threads at once. JDBC's connection system isn't specced to let you do this.
A transaction belongs to a single connection. You can't smear it out over multiples.
The obvious way to ensure that 'it is all rolled back' is to have a single long-lived transaction (but see later).
Combine these 3 facets and you end up with: Do all work in the async block. At least, all work that either needs to all happen, or none of it happens (i.e. the one transaction).
Any other basic approach wouldn't work or wouldn't be useful; there's no point freezing the main thread to wait for the async task (just do the async task on the spot; moving code to another thread doesn't magically make it go any faster. On the contrary, in fact).
However, transactions that aren't just long lived, but make a ton of changes to a DB is its own problem, but we now we're getting into the performance characteristics of your specific batch of queries and your particular DB engine, version, indices, and data. Kinda hard to answer with specifics, what with all those unknowns.
There are ways to design your DB to deal with this (mostly involving a table representing a calculation, and having a row indicate whether the calculation is complete or not. As long as you aren't done, dont set it to 'completed', and all your queries should ignore non-complete results. Upon bootup, delete (and with it, let that cascade) any non-complete results: Those must be half-baked work done right before your server crashed, and now you've restarted it). It's probably not the right answer here, just making sure you're aware that such options also exist.
As a general rule of thumb, countering a problem of "Our code has been observed to run too slowly" with "lets make it all async" doesn't work. async makes code harder to read, way harder to debug, and doesn't make stuff go faster. All you can really do with async is soothe the user by playing them some elevator music or slightly more pragmatic: A progress bar or whatnot, whilst they wait. And that's actually generally easier by spawning off the bits that tell the user what's happening into a separate thread, instead of asyncing the work itself. That, and make your algorithm better and/or fix your DB index definitions. You can search the web for that too; run EXPLAIN variants of your queries to make the DB tell you whether it is using any table sweeps (that's where it goes through the entire dataset before it can answer a query. You want to avoid those).
If you need help with either of those parts (show the user what is going on, instead of freezing the webpage or freezing the GUI / how to optimize a DB query), search the web for this information, there are tons of tutorials. Make sure to include the frontend tech; java can be used for swing apps, javafx, android, and there are at last count like a 100 web frameworks.

Android Studio Java Threads

I read about threads in Android Studio and I wanted to ask some questions. Are threads a must have in my application to avoid lag or only when you make really big and consuming apps? I am asking this because I have little lag on my app and I wanted to know if it is because I didn't use threads. I don't think it is because of useless stuff I did, I was pretty vigilant with that.
Threads are a vital component of building any large scale application. For example lets say you have a line of code that performs some unit of work which requires some time to be finished for example
...
// takes 500ms to complete could be a network operation/could be accessing camera,
// initializing recorder etc. (Initalizing recorder takes 100ms most of the time)
doSomeTimeIntensiveTask();
...
In such cases you would need to perform this task on a different thread and not on your UI/MAIN thread because for a end user using the application, IF you were to perform this on the UI/MAIN thread then he/she would notice the time delay as a stutter/lag kind of experience which makes for a bad UI experience in general.
Additionally there are tasks like making a HTTP request that require an in-determinate amount of time to actually finish in such cases, if such tasks was performed on the UI/MAIN thread then the application would be STUCK until the task was completed which sometimes causes the android OS to show pop up messages like the application doesn't seem to be responding do you want to force close the app? or some similar message, which again is bad user experience.
So in your case, I would try to identify exactly which piece of code is causing the lag in my UI/MAIN thread and put that part of the code in a separate thread and write a callback to continue executing correctly.
Without more information, it is impossible for anyone to answer this question in any reasonable manner.
Generally speaking, though, the main reasons to create additional threads (beyond the ones already used in the framework), is if you are doing heavy operations such as I/O (heavy read/write or http), graphics, or really complex calculations.
Look into Processes and Threads and AsyncTask.
To briefly quote the most relevant portion to this question:
When your app performs intensive work in response to user interaction, this single thread model can yield poor performance unless you implement your application properly. Specifically, if everything is happening in the UI thread, performing long operations such as network access or database queries will block the whole UI. When the thread is blocked, no events can be dispatched, including drawing events. From the user's perspective, the application appears to hang. Even worse, if the UI thread is blocked for more than a few seconds (about 5 seconds currently) the user is presented with the infamous "application not responding" (ANR) dialog. The user might then decide to quit your application and uninstall it if they are unhappy.

AsyncTasks are too slow for several simultaneous networking operations

I'm developing an app which must heavily interact with the server.So user input name and password and after authorization the next tasks must be performed:
The app has to fetch all incoming and outcoming messages for this user and load them to SQLite database.
Fetch all user friends (JSON with id,names,contact_data) and also load it to the app's database
Jump to the next activity and display income messages from the local database.
The problem this operations are too slow and when app starts new activity it is nothing to fetch from the database :AsyncTasks have not completed yet.I'm forced to use AsyncTask.get() in order to wait when they all complete but this takes over 16 seconds to wait!So what should I do: use threads, or before loading fetched data to database hold it in memory and display it in the new activity instead of fetching it from the database?But even without database tasks other fetching tasks take nearly 10 seconds to wait!So what should I do?
Oke a couple of things going pretty wrong here.
Do not use AsyncTasks for Networking. Use a service. In short, this is because your AsyncTask will stop, as soon as the Activity that started it will stop. This means that network requests get aborted easily and data goes lost and has to re-start again when the Activity is opened again.
Do not use .get() on AsyncTasks. This makes the UI thread wait for the task to complete, making the whole AsyncTask idea kinda useless. In other words: This blocks your UI.
What you should do:
Read up on using services. You can also have a look at a great opensource library called RoboSpice to help you with this.
Stop using .get() on AsyncTasks, if you want to know when it is done just use a listener.
Execute AsyncTasks on a threadpool ( myTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); ) when possible.
You should use a Service. This way it always can complete the tasks it was doing and you can complete all your tasks. Besides that you should initialize the app once, and after that only update the data.. that can't take 10 seconds.. than you're having an other problem.. But the nice thing of the service is that this can run in the background. see: Services in Android Tutorial
== Edit
Also take a look at GreenDao This library arranges fast SQlLite operations. Without the large setup!
AsyncTasks are not meant to run several small tasks concurrently at the same time. Quoting the docs
When first introduced, AsyncTasks were executed serially on a single background thread. Starting with DONUT, this was changed to a pool of threads allowing multiple tasks to operate in parallel. Starting with HONEYCOMB, tasks are executed on a single thread to avoid common application errors caused by parallel execution.
Use Threads in a ThreadPool when you want to run multiple tasks concurrently.
How you want to handle this situation is up to you. When the background tasks take too long, you can always show an alert dialog to the user and then take them to the activity once the data has been populated. Many apps show a 'Loading' screen when this happens. You can also show the 'Loading' Spinner control if no data is available yet. Never show a blank screen.
If the server side calls are under your control, employ some sort of caching to speed up the time. Any API call that lasts more than a second will make for an impatient user. If not employ one of the techniques mentioned in the previous paragraph. #Perception's technique is also one to consider if you can do it.

Handle Streaming data, update a GUI, use Threads, and not miss a beat?

This question is semi-theory, semi-how to properly code.
I am thinking about making an app in Java that will accepted streaming data, and as the data comes in, update a GUI.
So, what I am thinking of doing is just spawning off threads in Java that will:
collect data for X-milliseconds,
Take new data and update GUI with it
At the same time, start a new thread, collecting data for X milliseconds
This new thread must start off right where the first thread began
And, at the same time, all other parts of the program around going on in their own threads too.
So I need to make sure the threads don't collide, no data is lost in the mix, and I need to have an understanding of the speed limits. Say if the data is coming in at 1 Gbs vs 1 Mbs, what programming difference does that make?
The specific application includes data coming in from bluetooth and also data coming in from the Internet via an HTTPS rest API
If anyone has examples, either online or something quick and dirty right here, that'd be great. My Google searches came up dry..
The question is rather broad, but from an archtetctural point of view, I think the complexity decreases greatly if you change it to one thread reading from your device and putting the data into a buffer and one thread reading from that buffer and updating the UI. This reduces the code that needs to take care of multiple threads accessing it at the same time (idealy it reduces it to the buffer you use) and make synchronization much easier. It also decouples the fetching of the data from displaying it.
Writing the buffer can start off with using PipedInputStream and PipedOutputStream, however in one of my projects it turned out not to be fast enough if you really want to provide real-time processing and display, so you might end up writing yourself a low-latency buffer class.

Best practice when using threads in SWING / Java in general

I have a SWING UI that contains a button that creates a new SwingWorker thread. That thread then queries the SQLite database for results to put them in a JTable. In my StringWorker constructor, the parameters are various fields taken from other SWING components such as a JSpinner, JComboBoxes, etc.
Since I'm new to all of this thread thing, I'd like some advice from more knowledgeable programmers on how I should go about doing what I want to do.
I'd like to know if threads automatically end when I close the program with System.exit(0); so I don't end up with memory leaks
What is the best way to make sure I don't have two threads accessing my database at the same time (let's say the user clicks multiple times on the button or, other case, an administrator is updating the database with some files as input (within my program), then while the first thread is parsing the files and updating the database, he wants to query the database using the button, etc.).
Is it slower to use threads? At first I did all my calculations right in the EDT and of course the UI locked every time after pressing the button, but it only locked for about 5 seconds if I recall correctly. Now, when I press the button, it doesn't lock up but it seems like the result take about a little bit less than twice as long to show up in the JTable. Is it because I made a mistake in my code or is this normal?
I though about using a static field in the class the queries are in and setting it to true if it's in use. Is that the correct way of doing it? That way, not matter which thread is using the database, the second thread won't launch.
If it's not absolutely necessary (it shouldn't be), don't use System#exit in your code. Here are some explanations why and what is better.
Your database is capable of handling two concurrent requests, so it's not a bad thing in itself. If you use JDBC and its pooled connections via DataSource, then you should probably restrict the usage of one such a connection to one thread at a time. To cure the problem of having redundant database queries, e.g. when "clicking twice", there is probably more than one solution. I assume here that you mean the scenario where you have a Swing UI that is distributed to several people, and each of these instances talks to the same database -> simply disable your button as long as the execution of the database query takes.
It's slightly slower if you do not run your code directly in the Event Dispatch Thread due to scheduling of execution of your workers, but this should not be noticable. To see what goes wrong I would have to see the relevant code.
I'd like to know if threads automatically end when I close the program with System.exit(0);
Yes. Entire process will end and threads that are part of this process. However, if you don't call System.exit(), all non daemon threads must finish before process is gone.
What is the best way to make sure I don't have two threads accessing my database at the same time
Since it's a Swing application, I assume that both you and administrator can't access the application at the same time. However, to guarantee that even in single application you can't start more than one operation affecting database, you have to block UI. Either disable buttons or put glass pane on top of UI. Modal progress dialog is also helpful.
Is it slower to use threads?
No, it is not slower if done right. Slow operation will take as long as it takes. You can't fix it with threads, but you can, either keep speed (perceived) the same while providing nice, non blocking UI or you can do more than one slow operation at a time and therefore increase that perceived speed.

Categories