Foreground GC和Background GC

ART运行时的Foreground GC和Background GC

   它们是在ART运行时启动通过-Xgc和-XX:BackgroundGC指定的。但是在某同一段时间,ART运行时只会执行Foreground GC或者Background GC。也就是说,Foreground GC和Background GC在整个应用程序的生命周期中是交替执行的。这就涉及到从Foreground GC切换到Background GC,或者从Background GC切换到Foreground GC的问题。

     应用程序的两个状态:kProcessStateJankPerceptible和kProcessStateJankImperceptible。其 中,kProcessStateJankPerceptible说的就是应用程序处于用户可感知的状态,这就相当于是前台状态;而 kProcessStateJankImperceptible说的就是应用程序处于用户不可感知的状态,这就相当于是后台状态。

class Heap {
  // The process state passed in from the activity manager, used to determine when to do trimming and compaction.
  enum ProcessState {
    kProcessStateJankPerceptible = 0,
    kProcessStateJankImperceptible = 1,
  };
}

 这里是activity 启动时:

    public final class ActivityThread {        
        private class ApplicationThread extends ApplicationThreadNative {  
            ......  
      
            public final void scheduleLaunchActivity(Intent intent, IBinder token, int ident,  
                    ActivityInfo info, Configuration curConfig, CompatibilityInfo compatInfo,  
                    IVoiceInteractor voiceInteractor, int procState, Bundle state,  
                    PersistableBundle persistentState, List<ResultInfo> pendingResults,  
                    List<Intent> pendingNewIntents, boolean notResumed, boolean isForward,  
                    ProfilerInfo profilerInfo) {  
      
                updateProcessState(procState, false);  
      
                ActivityClientRecord r = new ActivityClientRecord();  
                ..................
      
                sendMessage(H.LAUNCH_ACTIVITY, r);  
            }


          public void updateProcessState(int processState, boolean fromIpc) {  
              synchronized (this) {  
                 if (mLastProcessState != processState) {  
                    mLastProcessState = processState;  
                    // Update Dalvik state based on ActivityManager.PROCESS_STATE_* constants.  
                    final int DALVIK_PROCESS_STATE_JANK_PERCEPTIBLE = 0;  
                    final int DALVIK_PROCESS_STATE_JANK_IMPERCEPTIBLE = 1;  
                    int dalvikProcessState = DALVIK_PROCESS_STATE_JANK_IMPERCEPTIBLE;  
                    // TODO: Tune this since things like gmail sync are important background but not jank perceptible.  
                    if (processState <= ActivityManager.PROCESS_STATE_IMPORTANT_FOREGROUND) {  
                        dalvikProcessState = DALVIK_PROCESS_STATE_JANK_PERCEPTIBLE;  
                    }  
                    VMRuntime.getRuntime().updateProcessState(dalvikProcessState);  
                    ......  
                 }  
              }  
          }   

          public void setProcessState(int state) {  
              updateProcessState(state, true);  
          } 
...... } ...... }

     每一个进程状态都通过一个整数来描述,其中,值越小就表示进程越重要。ART运行时将状态值大于等于PROCESS_STATE_IMPORTANT_FOREGROUND的进程都认为是用户可感知的,也就是前台进程,其余的进程则认为是用户不可感知的,也就是后台进程。通过这种方式,ApplicationThread类的成员函数updateProcessState就可以简化ART运行时对进程状态的处理。
       除了上述的Activity的Launch启动生命周期函数被ActivityManagerService通知调用时,Activity的Resume生命周期函数被ActivityManagerService通知调用调用时,也会发生类似的通过VMRuntime类的成员函数updateProcessState通知ART运行时应用程序状态发生了改变。对于其它的组件,例如Broadcast Receiver组件被触发时,Service组件被创建以及被绑定时,也会通过VMRuntime类的成员函数updateProcessState通知ART运行时应用程序状态发生了改变。
       不过,上述组件的生命周期对应的都是应用程序处于前台时的情况,也就是要求ART运行时从Background GC切换为Foreground GC的情况。当应用程序处于后台时,ActivityManagerService是通过直接设置应用程序的状态来通知ART运行时应用程序状态发生了改变的。
        ApplicationThread类实现了一个接口setProcessState,供ActivityManagerService直接设置应用程序的状态

public class ActivityManager {
    /** @hide Process is a persistent system process. */
    public static final int PROCESS_STATE_PERSISTENT = 0;

    /** @hide Process is a persistent system process and is doing UI. */
    public static final int PROCESS_STATE_PERSISTENT_UI = 1;

    /** @hide Process is hosting the current top activities.  Note that this covers
     * all activities that are visible to the user. */
    public static final int PROCESS_STATE_TOP = 2;

    /** @hide Process is hosting a foreground service due to a system binding. */
    public static final int PROCESS_STATE_BOUND_FOREGROUND_SERVICE = 3;

    /** @hide Process is hosting a foreground service. */
    public static final int PROCESS_STATE_FOREGROUND_SERVICE = 4;

    /** @hide Same as {@link #PROCESS_STATE_TOP} but while device is sleeping. */
    public static final int PROCESS_STATE_TOP_SLEEPING = 5;

    /** @hide Process is important to the user, and something they are aware of. */
    public static final int PROCESS_STATE_IMPORTANT_FOREGROUND = 6;

    /** @hide Process is important to the user, but not something they are aware of. */
    public static final int PROCESS_STATE_IMPORTANT_BACKGROUND = 7;

    /** @hide Process is in the background running a backup/restore operation. */
    public static final int PROCESS_STATE_BACKUP = 8;

    /** @hide Process is in the background, but it can't restore its state so we want
     * to try to avoid killing it. */
    public static final int PROCESS_STATE_HEAVY_WEIGHT = 9;

    /** @hide Process is in the background running a service.  Unlike oom_adj, this level
     * is used for both the normal running in background state and the executing
     * operations state. */
    public static final int PROCESS_STATE_SERVICE = 10;

    /** @hide Process is in the background running a receiver.   Note that from the
     * perspective of oom_adj receivers run at a higher foreground level, but for our
     * prioritization here that is not necessary and putting them below services means
     * many fewer changes in some process states as they receive broadcasts. */
    public static final int PROCESS_STATE_RECEIVER = 11;

    /** @hide Process is in the background but hosts the home activity. */
    public static final int PROCESS_STATE_HOME = 12;

    /** @hide Process is in the background but hosts the last shown activity. */
    public static final int PROCESS_STATE_LAST_ACTIVITY = 13;

    /** @hide Process is being cached for later use and contains activities. */
    public static final int PROCESS_STATE_CACHED_ACTIVITY = 14;

    /** @hide Process is being cached for later use and is a client of another cached
     * process that contains activities. */
    public static final int PROCESS_STATE_CACHED_ACTIVITY_CLIENT = 15;

    /** @hide Process is being cached for later use and is empty. */
    public static final int PROCESS_STATE_CACHED_EMPTY = 16;
}

每一个进程状态都通过一个整数来描述,其中,值越小就表示进程越重要。ART运行时将状态值大于等于PROCESS_STATE_IMPORTANT_FOREGROUND的进程都认为是用户可感知的,也就是前台进程,其余的进程则认为是用户不可感知的,也就是后台进程。通过这种方式,ApplicationThread类的成员函数updateProcessState就可以简化ART运行时对进程状态的处理。

    static void VMRuntime_updateProcessState(JNIEnv* env, jobject, jint process_state) {  
      Runtime::Current()->GetHeap()->UpdateProcessState(static_cast<gc::ProcessState>(process_state));  
      ......  
    }  

 

void Heap::UpdateProcessState(ProcessState process_state) {
  if (process_state_ != process_state) {
    process_state_ = process_state;if (process_state_ == kProcessStateJankPerceptible) {
      // Transition back to foreground right away to prevent jank.
      RequestCollectorTransition(foreground_collector_type_, 0);
    } else {
      // Don't delay for debug builds since we may want to stress test the GC.
      // If background_collector_type_ is kCollectorTypeHomogeneousSpaceCompact then we have
      // special handling which does a homogenous space compaction once but then doesn't transition
      // the collector.
      RequestCollectorTransition(background_collector_type_,
                                 kIsDebugBuild ? 0 : kCollectorTransitionWait);
    }
  }
}

    如果是从kProcessStateJankImperceptible状态变为kProcessStateJankPerceptible状态,那么就调用Heap类的成员函数RequestCollectorTransition请求马上将当前的GC设置为Foreground GC。
    如果是从kProcessStateJankPerceptible状态变为kProcessStateJankImperceptible,那么就调用Heap类的成员函数RequestCollectorTransition请求将当前的GC设置为Background GC。注意,在这种情况下,对于非DEBUG版本的ART运行时,不是马上将当前的GC设置为Background GC的,而是指定在kCollectorTransitionWait(5秒)时间后再设置。这样使得进程进入后台运行的一小段时间内,仍然可以使用效率较高的Mark-Sweep GC。

 

posted @ 2016-03-13 13:09  牧 天  阅读(1378)  评论(0)    收藏  举报