What Is the Android UI Thread Stack Size Limit and How to Overcome It

What is the android UI thread stack size limit and how to overcome it?

I believe that the main thread's stack is controlled by the JVM - in Android's case - Dalvik JVM. The relevant constant if I'm not mistaken is found in dalvik/vm/Thread.h under #define kDefaultStackSize

Browsing for stack sizes through the dalvik source history:

  • API 3 (Android 1.5) = 8KB

  • API 4-10 (Android 1.6 - Android 2.3.7) = 12KB

  • API 14-17 (Android 4.0 - Android 4.2.2) = 16KB

So how many nested views can you have:

Impossible to say accurately. Assuming the stack sizes are as described above, it all depends on how many function calls you have in your deepest nesting (and how many variables each function takes, etc). It seems that the problematic area is when the views are being drawn, starting with android.view.ViewRoot.draw(). Each view calls the draw of its children and it goes as deep as your deepest nesting.

I would perform empirical tests at least on the devices appearing in all the boundary groups above. It seems that using the emulator gives accurate results (although I've only compared the native x86 emulator to a real device).

Keep in mind that optimizations to how the actual widgets / layouts are implemented may also influence this. Having said that, I believe that most of the stack space is eaten by every layout hierarchy adding about 3 nested function calls: draw() -> dispatchDraw() -> drawChild() and this design hasn't changed much from 2.3 - 4.2.

setting stack size to thread seems to make no difference in android

This is well documented in the JavaDoc for Thread. Quoting:

The details of the relationship between the value of the stackSize parameter and the maximum recursion depth and concurrency level are platform-dependent. On some platforms, the value of the stackSize parameter may have no effect whatsoever.

Create the UI thread manually in Android in order to increase its small stack size

CommonsWare is sadly mistaken. Closer inspection shows that the default stack size on Android 2.x is 12KB and in Android 4.x has been increased to 16KB. This means the core team was aware of the small stack issue and fixed it. Sad to say, but these extra 4KB is what makes all the difference in crashes.

Furthermore, if you are using common libraries like ABS and support v4 - these libraries add the extra views to your layout whenever you are using fragments. Since most of us rely on these libraries, saying that fragments can easily be added with 1 view is simply incorrect. If you are using ABS+support lib you will pay 3 views per fragment. And you will start off with a minimum of 5 views (for ABS layout).

Regarding creating a UI thread manually, this may be possible and will probably not require to root the device or change its firmware. These were also bold statements that are probably incorrect.

Finally, I've decided against creating my own UI thread with large stack. Instead, I've chosen to completely drop the use of fragments from my code. This saved me a total of 5 views in my layout. Everything that fragments give you, can also be done by adding ViewGroups manually. It's just a little more code, but nothing too complex. It seems that fragments are a little useless and if you don't have the luxury of using them - that's the first place to cut.

Android: Increase call stack size

You might not be able to increase call stack size in the main UI Thread(which is understandable because you're supposed to do as few things as possible here), but you can do it in a separate thread by making use of the Thread object's constructor parameters:

ThreadGroup group = new ThreadGroup("threadGroup");
new Thread(group, runnableObject, "YourThreadName", 2000000).start();

With this example I increased my stack size from 8k (around 260 calls) to 2M (enough for not to get the StackOverFlowException, of course you can add as much as you want as long as the memory can take it), so in the end, for further readers, this is the way you can increase your stack size,although is not recommended, in some cases it's actually necessary for example an algorithm with extensive recursive calls and of course by doing all the hard work in a worker thread(as you're supposed to) with your specified stack size and just "posting" changes in UIs using the main UI Thread with Handlers or whatever mechanism you would like to use to interact with it...

Hope this Helps...

Regards!

How to get the stack size

I have a deep hierarchy in my app

That's not a good idea, regardless of stack space. The more views in your hierarchy, the more expensive the rendering process is. Use Hierarchy View to examine your view hierarchy and find ways to remove unnecessary items (e.g., use compound images with TextView widgets rather than using separate ImageView widgets inside of a LinearLayout).

I need to know what is the size of the stack of the device. Is there a way to know?

There is nothing in standard Java or in Android that will return the stack size.

Maximum number of thread Android

As commented by @Xaver Kapeller, you may create as many Threads you want but more thread not actually the part of the solution.

A core(CPU) in Processor will handle only one Task(Process or Thread) at a given time.

so in Processor with 1 core will handle one thread at a time. so technically no matter how many threads you open for this processor it will serve a thread at a given time. All threads which are running would be using processor sequentially, utilizing quantum time of processor which only seems to be concurrent.

Processor with 2 core will handle 2 threads at a time( concurrent execution of two threads).

Processor with 4 core will handle 4 threads at a time( concurrent execution of four threads.

Processor with 8 core will handle 8 threads at a time( concurrent execution of eight threads. so on

Maximum number of LinearLayout's that can be nested in a single XML file?

View tree depth is in practice limited by the UI thread stack size that is needed for the recursive traversal of the view tree in measure/draw operations. The stack size depends on the API level and is 8kB, 12kB or 16kB. There isn't a specific number as the depth limit; in practice you'll see StackOverflowErrors in low-spec devices after a couple dozen nested views or so.

Lint will nag if you have nesting level 10 or deeper in a single layout file. It doesn't analyze the runtime layout hierarchy depth.

Consider keeping your view hierarchies as flat as possible.

Update a java thread's stack size at runtime

The stack size dynamcally updates itself as it is used so you never need to so this.

What you can set is the maximum size it can be with -Xss This is the virtual memory size used and you can make it as large as you like on 64-bit JVMs. The actual memory used is based on the amount of memory you use. ;)

EDIT: The important distinction is that the maximum size is reserved as virtual memory (so is the heap btw). i.e. the address space is reserved, which is also why it cannot be extended. In 32-bit systems you have limited address space and this can still be a problem. But in 64-bit systems, you usually have up to 256 TB of virtual memory (a processor limitation) so virtual memory is cheap. The actual memory is allocated in pages (typically 4 KB) and they are only allocated when used. This is why the memory of a Java application appears to grow over time even though the maximum heap size is allocated on startup. The same thing happens with thread stacks. Only the pages actually touched are allocated.



Related Topics



Leave a reply



Submit