Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IO operation in other thread blocking my UI thread?

So that IO doesn't block the UI thread in my Android app, I'm trying to move a file write operation into a separate thread. This is the code I'm using to start a low priority thread to write about 1Mb from a byte buffer:

Thread t = new Thread(new Runnable()
{
  @Override
  public void run()
  {
    Process.setThreadPriority(Process.THREAD_PRIORITY_BACKGROUND);
      try
      {
        FileOutputStream fos = new FileOutputStream(filename));
        try
        {
          final java.nio.channels.FileChannel outChannel = fos.getChannel();
          outChannel.write(byteBuffer);
          fos.getFD().sync();
        }
        finally
        {
          if (fos != null)
            fos.close();
        }
      }
    catch (Exception e)
    {
      e.printStackTrace();
    }
}
});

t.setPriority(Thread.MIN_PRIORITY);
t.start();

These threads are started in my app when certain UI events happen. Unfortunately, I still notice a huge amount of lag sometimes. My UI will freeze for ~2 seconds every 10 or so times I start/finish one of the above threads. If I comment out the thread code, these delays disappear.

What can I do to stop this IO operation from blocking my UI thread?

I'm not sure what to do now to diagnose the problem. My understand was that the IO thread would become blocked when "outChannel.write" happened as it was waiting for an IO operation to finish, which would mean my UI thread would immediately take over. Is it the case the write operation actually requires a big chunk of CPU power?

Edit:

With StrictView on (which I'm sure of because it caught some unrelated IO problems in the UI thread that I fixed first), I can confirm no IO occurs in my IO thread.

The results of running traceview are quite puzzling. The UI problem is that, when I'm performing drag and drop actions, every 10 or so times I do this the device seems to freeze for about 0.5 to 1s. The thing you're dragging will freeze and after a delay will eventually jump to where your finger is. In traceview, I kept dragging and dropping until this happened. For the case where this happens in traceview, my background threads aren't running but there's a sudden block of about 1 second where operations on my UI thread that are usually fast to call are taking about x10 longer to perform. For example, a call to .drawBitmap (with a fixed size bitmap) is shown as taking ~0.2s to execute when every time before this the same .drawBitamp call is taking a tenth of this time. I could just be reading it wrong, but I don't know where to go from here or what to look for.

like image 795
rbcc Avatar asked Dec 10 '25 03:12

rbcc


1 Answers

What can I do to stop this IO operation from blocking my UI thread?

The I/O operation is not blocking the main application thread directly. Your code running on the main application thread is blocking the main application thread. You need to determine where your code running on the main application thread is getting tied up. To do this, use a debugger, or Log.d() statements, or whatever.

For example, on most Android devices, the filesystem is YAFFS2, which has a per-partition global lock. Quoting Brad Fitzpatrick:

yaffs has a giant lock around the whole filesystem code, so even a tiny stat() can block for seconds if the disk is otherwise being hammered by something else (during boot, heavy sync, etc).

Hence, if you are tying up the filesystem for seconds in your background thread, the main application thread will be unable to do file I/O of its own. Perhaps that is what is tripping you up, in which case StrictMode in Android 2.3 can help you identify the source of your difficulty.

What's the point of moving it to another thread then?

The point is to move the flash I/O off the main application thread. All flash I/O.

FWIW, Android will be appearing on ext4 devices (e.g., Nexus S), and this issue falls away...though you need to then worry about the sync() calls. On YAFFS2, sync() is less critical, by and large, since it does little buffering.

like image 142
CommonsWare Avatar answered Dec 12 '25 19:12

CommonsWare



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!