View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *     http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  
19  package org.apache.giraph.utils;
20  
21  import org.apache.giraph.conf.GiraphConstants;
22  import org.apache.giraph.conf.ImmutableClassesGiraphConfiguration;
23  import org.apache.giraph.master.MasterObserver;
24  import org.apache.giraph.worker.WorkerObserver;
25  import org.apache.log4j.Logger;
26  
27  /**
28   * An observer for both worker and master that periodically dumps the memory
29   * usage using jmap tool.
30   */
31  public class JMapHistoDumper implements MasterObserver, WorkerObserver {
32    /** Logger */
33    private static final Logger LOG = Logger.getLogger(JMapHistoDumper.class);
34  
35    /** How many msec to sleep between calls */
36    private int sleepMillis;
37    /** How many lines of output to print */
38    private int linesToPrint;
39    /** Should only print live objects */
40    private boolean liveObjectsOnly;
41  
42    /** The jmap printing thread */
43    private Thread thread;
44    /** Halt jmap thread */
45    private volatile boolean stop = false;
46  
47    @Override
48    public void preLoad() {
49      // This is called by both WorkerObserver and MasterObserver
50      startJMapThread();
51    }
52  
53    @Override
54    public void postSave() {
55      // This is called by both WorkerObserver and MasterObserver
56      joinJMapThread();
57    }
58  
59    @Override
60    public void preApplication() {
61    }
62  
63    @Override
64    public void postApplication() {
65    }
66  
67    /**
68     * Join the jmap thread
69     */
70    private void joinJMapThread() {
71      stop = true;
72      try {
73        thread.interrupt();
74        thread.join(sleepMillis + 5000);
75      } catch (InterruptedException e) {
76        LOG.error("Failed to join jmap thread");
77      }
78    }
79  
80    /**
81     * Start the jmap thread
82     */
83    public void startJMapThread() {
84      stop = false;
85      thread = new Thread(new Runnable() {
86        @Override
87        public void run() {
88          while (!stop) {
89            JMap.heapHistogramDump(linesToPrint, liveObjectsOnly);
90            try {
91              Thread.sleep(sleepMillis);
92            } catch (InterruptedException e) {
93              LOG.info("JMap histogram sleep interrupted", e);
94            }
95          }
96        }
97      });
98      thread.setDaemon(true);
99      thread.start();
100   }
101 
102   @Override
103   public void preSuperstep(long superstep) { }
104 
105   @Override
106   public void postSuperstep(long superstep) { }
107 
108   @Override
109   public void applicationFailed(Exception e) { }
110 
111   @Override
112   public void setConf(ImmutableClassesGiraphConfiguration configuration) {
113     sleepMillis = GiraphConstants.JMAP_SLEEP_MILLIS.get(configuration);
114     linesToPrint = GiraphConstants.JMAP_PRINT_LINES.get(configuration);
115     liveObjectsOnly = GiraphConstants.JMAP_LIVE_ONLY.get(configuration);
116   }
117 
118   @Override
119   public ImmutableClassesGiraphConfiguration getConf() {
120     return null;
121   }
122 }