Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

18 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

AndroidMultiProcessPlayground

An Android app that allows for easy experimention of:

  • BIND_* flags for bindService()
  • OutOfMemory handling
  • Thread priorities

Build & Run:

./gradlew assembleDebug
adb install -r app/build/outputs/apk/app-debug.apk
adb shell am start -n com.example.agrieve.multiprocessdemo/.MainActivity

How to use it

  1. Start the app & connect your device with a USB cable
  2. On your host machine, navigate to chrome://inspect/#devices
  3. Click on the "Stetho" link
  4. Type init() into the JS console.
  5. Try out example workflows, but DO NOT copy & paste them more than one line at a time or you may execute commands too quickly.

Example Workflow #1 - BIND flags

In devtools:

ren1 = api.createRenderer()
// Show what bindings they have enabled:
api.listBindings()
// Add a custom binding:
api.bindService('Service1', ['BIND_AUTO_CREATE', 'BIND_ADJUST_WITH_ACTIVITY'])
// Remove existing binding:
ren1.moderateBinding.unbind()
// Show OOM buckets via /proc/PID/oom_score_adj
api.listOomScores()

In a terminal:

# See OOM buckets and memory use:
adb shell dumpsys meminfo

Example Workflow #2 - OOM Order and Task Stacks

In devtools:

// Create a process bound to main activity
api.createRenderer()
// Switch to a different activity stack
api.startAffinityActivity()
api.createRenderer()

In a terminal:

# Show which OOM bucket each bound service ends up in.
adb shell dumpsys activity | sed -n -e '/dumpsys activity processes/,$p'
# Note that both services are always together despite being bound by different activities.

Example Workflow #3 - Explicit OOM ordering with BIND_ABOVE_CLIENT

In devtools:

// Create all 8 renderers, and each one create a BIND_ABOVE_CLIENT binding on the previous one.
api.createAllRenderers(0, true);  // First 4.
api.createAllRenderers(0, true);  // Second 4.

In a terminal:

# Show which OOM bucket each bound service ends up in.
adb shell dumpsys activity | sed -n -e '/dumpsys activity processes/,$p'

In devtools:

// Remove all "vis" bindings
renderers.forEach(function(r) { r.moderateBinding.unbind(); })

In a terminal:

# Show which OOM bucket each bound service ends up in.
adb shell dumpsys activity | sed -n -e '/dumpsys activity processes/,$p'
# Switch apps a few times while repeating this step.

Example Workflow #4 - OOM Killing in Action

In devtools:

// Create 4 child services (ren1, ren2, ren3, ren4), have each consume 100meg
api.createAllRenderers(100)
// Show what bindings they have enabled:
api.listBindings()
api.consumeNativeMemoryUntilLow()

In a terminal:

# Watch memory usage go up and apps disappear from cached list
adb shell dumpsys activity | sed -n -e '/dumpsys activity processes/,$p'
# Or use meminfo (but it doesn't show separate background buckets):
adb shell dumpsys meminfo

In devtools:

// This function stops as soon as an onTrimMemory callback is called.
// Call it again to reach the next threshold.
api.consumeNativeMemoryUntilLow()
api.consumeNativeMemoryUntilLow()

Example Workflow #5 - Thread Priorities

In devtools:

// Create 4 native threads, and 4 java threads, all at different priorities.
api.createAllWorkers()
// Show performance of each thread
api.listWorkers()

In a terminal:

# List all threads of the process
adb shell top -n 1 | grep multiprocessdemo
# Monitor CPU usage of top threads
adb shell top -m 20 -t

In devtools:

// Create workers on another process.
api.createAllRenderers()
ren1.createWorker(9)
// Starting at 10, threads go to a low-power cgroup.
ren1.createWorker(10)
api.listWorkers()

Example Workflow #6 - BIND_NOT_FOREGROUND

In devtools:

// Create a workers with & without BIND_NOT_FOREGROUND.
ren1 = api.createRenderer()
ren2 = api.createRenderer(['BIND_NOT_FOREGROUND'])
// Create 2 threads per process of equal priority
ren1.createWorker(0)
ren1.createWorkerNative(0)
ren2.createWorker(0)
ren2.createWorkerNative(0)
// Show performance of each thread
api.listWorkers()

In a terminal:

# Monitor CPU usage of top threads
adb shell top -m 20 -t

Example Workflow #7 - Changing Thread Priorities

In devtools:

api.createWorker(0)
api.createWorker(0)
api.createWorker(10)
// Show performance of each thread
api.listWorkers()

workerThreads[2].setNice(0)
api.resetWorkerStats()
// Show that changed priority worked.
api.listWorkers()

Example Workflow #8 - Querying Current Trim Level

In devtools:

api.createRenderer()
api.createRenderer()
api.createRenderer()
api.printMemoryInfo()  // Look at lastTrimLevel

ren1.consumeNativeMemoryUntilLow()
api.printMemoryInfo()  // lastTrimLevel is now > 0

ren1.moderateBinding.unbind()
ren2.moderateBinding.unbind()
ren3.moderateBinding.unbind()

api.printMemoryInfo()  // lastTrimLevel is now 0 again
// Note also that no onTrimMemory log is shown for this transition.

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages