Suppose you have an application that spawns a local HTTP server on an Android device.
Will there be any advantage to running it in a separate application instead of spawning a separate thread?
Since the heap size is capped per application, I'm assuming that there is more breathing space for memory when running a separate application.
Apart from this, in terms of performance are there any other benefits (or disadvantages) such as a bigger chunk of CPU time?
The one big disadvantage I see that happens when running application components in different threads is that the two parts will be in different DVMs. This can make sharing Preference changes, Listeners, Observers, ect, not work as you would expect, you would also have to make sure all DB access is synchronized.
To counter this point if you synchronization correctly and don't need preferences you can use bundles or AIDL to communicate back and forth from the 2 applications. The best bet is AIDL for 2-way continuous communication, but be aware AIDL can be expensive. The other option for communication is a socket... but this goes against the SDK that is provided. A trick I have learned when doing this is to create an API jar file to include in both applications that will handle all communications (by way of intent or AIDL - blackbox approach).
Personally I think application components that are similar should stay in the same DVM and application unless they can run as stand alone then you have to be the judge of that.
Have you though about running the HTTP server as on ongoing foreground service? This would uncouple your design as well as make things easy and lighter.
Using separate processes can significantly increase the memory footprint of your app. Not only do you get a multiple of the core Dalvik overhead (figure 2-3MB per process), but none of the RAM used by your app can be shared (such as static symbols and such in your code).
Plus you have more CPU overhead because you now need to do IPC for any interaction between those different parts of your app that cross boundaries. And you have a lot more complexity in implementation because you actually need to implement that IPC and figure out how to correctly manage these different parts of the app that are running in isolated address spaces.
For the vast majority of situations, I don't think it is good to use multiple processes.
There is a remote service example in SDK.
If you go with two apps, you will absolutely need remote service. And that is only way to communicate among apps, as my experience.
From my viewpoint, it is not good with the concept "server" to be used on a cell phone. But perhaps you have your reason...
First, you don't need separate application for that, you define another process for your own application. In most cases doing such thing will boost your performance because there is bigger chance that your process will actually run on separated physical process. How ever the Android OS does not support this yet, not event in Android 4.03.
So the only benefit you will get from this is memory, witch in my opinion should not be a reason for opening another process.
In most cases you will get a boost in the performance of you app if you run your server in a separate process via service but not always.
NOTE: service can run in a separate process of its own but for that you have to provide android:service tag in the xml.
One big flaw in this type of design which I think you already know is that , in android each process runs in its own virtual machine.So if you spawn a new process it will get its own VM. Now you yourself consider which is better.Running one VM for the whole application or running two of them. (In most cases I have heard of at least in android 1 VM is more than sufficient to handle everything you need)
Apart from that another flaw is that when you separate the process from the main process of your app e.x you are running your server service in a separate process then it may not shutdown even though your app comes across an exception or error as its a separate process from that of the main process and is not tied to the life cycle of your app anymore.So it can lead to some unexpected behavior and can cause your app to malfunction.
If you are OK to take the risk than go with it otherwise go with threads(I would recommend Asynctask within a service) for the purpose you are seeking as it will provide you with almost the same functionality while being safe inside the application scope/lifecycle.
hope this helps.
Related
Typically, processes aren't expected to do any work when cached, but some apps might have custom features supported by processes that are expected to run while cached.
This quote comes from Android Source Code Document .
What is the custom features that can be running in cached processes. As I understand it, cached processes do not contain any running Android component, so does it mean that programs can be run without any component or cached processes may contain running components?
I think so no because minimum one activity is required for run the android programme.
Know more about android fundamentals and android activities
https://developer.android.com/guide/components/fundamentals
How can I know the flow if more than two threads are in use , as in case of any networking library like VOLLEY , ASYSNCTASK etc .?
You can see the sequence of threads by logging, but by definition you can't possibly know when exactly threads will execute since it's not deterministic. Who decides this is the kernel based on some internal rules and Android has some "layers" built on top of the Linux Kernel that allow you to somehow control the priority of your threads. What this means is: everytime you run your application the order of the methods inside threads will change.
I recommend you to watch this presentation where this is explained in detail: https://www.youtube.com/watch?v=xQoc1nSvvMw
There is one tool that can help you to debug threads: Dalvik Debug Monitor Server (DDMS) https://developer.android.com/studio/profile/ddms.html
Here is a post explaining how to use it https://www.toptal.com/android/android-ddms-ultimate-power-console
As the title states,
Why is there a separate instance of VM(Dalvik/ART) for every App on Android?(the need for it)
and, what would have happened if the Android OS had chosen a model where a single VM runs all the apps?
There are many reasons why running multiple applications in a single process doesn't work; here's two:
Security zones.
Two applications that don't trust one another shouldn't be able to view each other's memory, even if they use native code or reflection.
Failure isolation.
If a process leaks memory and crashes, it harms only itself.
Why there is a separate instance of VM(Dalvik/ART) for every App?(the
need for it)
It is a design decision, and in my opinion, is made to keep it simple. Every process runs in its own vm. All the resources are allocated to that process, and the vm, internally, has not to coordinate access to resources, e.g. FileDescriptors, I/O etc. I never heard of multiprocess vm (a vm that allows more than one process to run in it), but I found an article that you could give you an insight.
On a recent SO question, I explained how calling a RenderScript kernel multiple times will effectively force all threads to be globally synchronized between calls.
I am currently working with multiple convolutions applied in sequence to image data. Since the convolution algorithm requires reading surrounding pixel data of the input image, I have implemented a workflow where my own custom kernel is called multiple times -- to make sure that at every step, all data from the previous convolution is ready and available at the correct coordinates. This technique has worked great for me so far.
However, in my constant quest for optimization, I have noticed that there is much performance to be obtained by keeping intermediate values in local registers for a thread, instead of writing them back to the global memory allocation in between kernel calls. If I were able to chain these convolutions in such a way, things would run much quicker. The problem is obviously that accessing the registers of surrounding threads is not really possible. Furthermore, this would require threads to run in synch to make sure these intermediate values in between stages get calculated in the expected order.
In CUDA and OpenCL, these issues are very common, and are addressed by well-known barrier synchronization + shared memory tiling techniques, which in turn depend on the concept of CUDA thread blocks or OpenCL work groups. I believe these concepts are non-existent in RenderScript, as this issue is very much tied to the wildly different architectures between desktop-class GPU's and mobile SoC's.
So my obvious question here is, are such things possible in RenderScript? That is, better management of threads and possibly thread groups for quicker data sharing among them.
On the Google I/O 2013 RenderScript talk by Jason Sams and Tim Murray, it is discussed how Script Groups might be able to do some behind the scenes optimizations, such as cross-device parallelization, memory tiling, and kernel fusion; all this by analyzing at runtime the dependency DAG in the group, and either automatically creating allocations where needed or possibly optimizing them away. I'm assuming this last bit referes to fusing kernels so that they work off their own local data, kind of how I mentioned above keeping data in local registers and combining separate steps inside a single kernel.
All this seems very much in line with what I'm looking for, especially since my application is indeed a well-defined DAG of inter-dependent operations (for a Convolutional Neural Network). So if Script Groups are indeed a plausible mobile-centric alternative to these mechanisms, I'm wondering if there is any way of influencing how and where these optimizations happen. Or if not, how much can the runtime be trusted to make the correct inference from my data dependencies given the hardware its running on -- in the specific case of "surrounding" pixel data access of the convolutional algorithm.
I realize this might all still be work in pogress, and methods would be highly hardware dependent at this point. So if there is no straight solution for such matters at the present time -- I'd be very much willing to accept a speculative answer on how this kind of workflow might potentially be approached by RenderScript in future releases.
I'd be immensely grateful on some insight about this, as it would greatly affect the development direction of my own project going forward, not to mention there are surely many other people out there wondering how such general parallel computing tasks can be handled in RS.
Thank you very much!
As you've discovered, there's no way in RS to directly share data across threads. However, what you are describing can be done using a ScriptGroup. The catch is that each script in the group has to be unique, so you cannot feed your same script over and over. At least, not as it is written now. You could certainly put the "core" of your script in a RS header and include it from multiple kernels. The ScriptGroup allows you to have the output from one script become the input of another, or the output of one script becomes a global field in another. The documentation states that the kernel to kernel (output to input) is the more efficient use case. Using this approach, your synchronization issue would be resolved as the engine will execute the first script against the entire input data set before starting the second script, etc. The scripts themselves will be parallelized appropriately for the hardware (using either CPU or GPU/DSP). The engine will not have to pop back out to Java between scripts and can also manage the data allocations behind the scenes, if needed.
Something you may notice is the ScriptGroup utilizes Script.KernelID or Script.FieldID in order to identify the exact script or field in which to connect two kernels. Your custom scripts have these things auto-generated as long as you explicitly call out your kernel function using the RS compiler attribute pragma. Then you can call getKernelID_<name> (where 'name' is the kernel function name from your script) to get the kernel ID.
I'm trying to follow Android best practices, so in debug mode I turn all the following on:
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectAll().penaltyLog().build()); //detect and log all thread violations
StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectAll().penaltyLog().build()); //detect and log all virtual machine violations
Android now yells at me when I try to use any sort of file access or SQL in the main (UI) thread. But I see so many recommendations to use file access and/or SQL in the main thread. For example, the main activity should load default preference values inside onCreate() in case they haven't been set yet:
PreferenceManager.setDefaultValues(context, resId, readAgain);
Oops---that results in a file access on the first application execution, because onCreate() is called on the UI thread. The only way around it I can see is to start a separate thread---which introduces a race condition with other UI code that might read the preferences and expect the default values to already be set.
Think also of services such as the DownloadManager. (Actually, it's so buggy that it's useless in real life, but let's pretend it works for a second.) If you queue up a download, you get an event (on the main thread) telling you a download has finished. To actually get information about that download (it only gives you a download ID), you have to query the DownloadManager---which involves a cursor, giving you an error if you have a strict policy turned on.
So what's the story---is it fine to access cursors in the main thread? Or is it a bad thing, and half the Android development team and Android book authors forgot about that?
The only way around it I can see is to start a separate thread---which introduces a race condition with other UI code that might read the preferences and expect the default values to already be set.
Then use an AsyncTask, putting the setDefaultValues() call in doInBackground() and the "other UI code that might read the preferences" in onPostExecute().
To actually get information about that download (it only gives you a download ID), you have to query the DownloadManager---which involves a cursor, giving you an error if you have a strict policy turned on.
So query the DownloadManager in a background thread.
So what's the story---is it fine to access cursors in the main thread?
That depends on your definition of "fine".
On Android 1.x and most 2.x devices, the filesystem used is YAFFS2, which basically serializes all disk access across all processes. The net effect is that while your code may appear sufficiently performant in isolation, it appears sluggish at times in production because of other things going on in the background (e.g., downloading new email).
While this is a bit less of an issue in Android 3.x and above (they switched to ext4), there's no question that flash I/O is still relatively slow -- it will just be a bit more predictably slow.
StrictMode is designed to point out where sluggishness may occur. It is up to you to determine which are benign and which are not. In an ideal world, you'd clean up them all; in an ideal world, I'd have hair.
Or is it a bad thing, and half the Android development team and Android book authors forgot about that?
It's always been a "bad thing".
I cannot speak for "half the Android development team". I presume that, early on, they expected developers to apply their existing development expertise to detect sluggish behavior -- this is not significantly different than performance issues in any other platform. Over time, they have been offering more patterns to steer developers in a positive path (e.g., the Loader framework), in addition to system-level changes (e.g., YAFFS2->ext4) to make this less of a problem. In part, they are trying to address places where Android introduces distinct performance-related challenges, such as the single-threaded UI.
Similarly, I cannot speak for all Android book authors. I certainly didn't focus on performance issues in early editions of my books, as I was focusing on Android features and functions. Over time, I have added more advice in these areas. I have also contributed open source code related to these topics. In 2012, I'll be making massive revisions to my books, and creating more open source projects, to continue addressing these issues. I suspect, given your tone, that I (and probably others) are complete failures in your eyes in this regard, and you are certainly welcome to your opinion.