package org.apache.hadoop.mapred; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.mapred.ControlGroup.CPUControlGroup; /** * Limits CPU usages of each Task through a Linux cpu control group. * * Requirement: * <ul> * <li>A cpu sub-system control group is available</li> * <li>A path to a target control group is configured * (mapred.tasktracker.cgroup.cpu.root) or the default path will be used * (/cgroup/cpu)</li> * <li>A user launching Task has a permission to modify a control group (i.e. * using chown)</li> * </ul> */ public class TaskTrackerCPUControlGroup { private static Log LOG = LogFactory.getLog(TaskTrackerCPUControlGroup.class); public static final String CGROUP_CPU_ROOT_PROPERTY = "mapred.tasktracker.cgroup.cpu.root"; public static final String DEFAULT_CGROUP_CPU_ROOT = "/cgroup/cpu/tasktrackers"; public static final String CGROUP_TRASH_GROUP_NAME = "trash"; private boolean isAvailable; private long baseShare; private CPUControlGroup ttcgp; private CPUControlGroup trashcgp; public TaskTrackerCPUControlGroup(Configuration conf, int slots) { String rootpath = conf.get(CGROUP_CPU_ROOT_PROPERTY, DEFAULT_CGROUP_CPU_ROOT); ttcgp = new CPUControlGroup(rootpath); if (!CPUControlGroup.isAvailable()) { LOG.warn("TaskTrackerCPUControlGroup is disabled because a cpu sub-system is not available"); isAvailable = false; return; } if (!ttcgp.canControl()) { LOG.warn("TaskTrackerCPUControlGroup is disabled because TaskTracker does not have an appropriate permission for " + rootpath); isAvailable = false; return; } isAvailable = true; baseShare = CPUControlGroup.CPU_SHARES_DEFAULT; ttcgp.setCPUShares(baseShare*slots); trashcgp = ttcgp.createSubGroup(CGROUP_TRASH_GROUP_NAME); trashcgp.setCPUShares(baseShare); LOG.info("TaskTrackerCPUControlGroup is created with " + slots + " slots"); } public void addTask(String taskname, String pid) { if (!isAvailable) return ; CPUControlGroup taskcgp = ttcgp.createSubGroup(taskname); taskcgp.setCPUShares(baseShare); taskcgp.addToGroup(pid); } public void removeTask(String taskname) { if (!isAvailable) return ; CPUControlGroup taskcgp = ttcgp.getSubGroup(taskname); trashcgp.addToGroup(taskcgp.getThreadGroupList()); taskcgp.deleteGroup(); } }