use of edu.snu.mist.core.task.groupaware.eventprocessor.EventProcessor in project mist by snuspl.
the class FirstFitRebalancerImpl method makeBinsAndItems.
/**
* Makes bins (event processors with the available size) and items (groups).
* @param desirableLoad desirable load (size)
* @param loadTable load table
* @param eventProcessors event processors
* @return bins and items
*/
private Tuple<Map<EventProcessor, Double>, List<Group>> makeBinsAndItems(final double desirableLoad, final Map<EventProcessor, Double> loadTable, final List<EventProcessor> eventProcessors) {
// Make bins
final Map<EventProcessor, Double> bins = new HashMap<>(groupAllocationTable.size());
// Make items
final List<Group> items = new LinkedList<>();
for (final EventProcessor eventProcessor : eventProcessors) {
double load = loadTable.get(eventProcessor);
if (load > desirableLoad) {
// Add groups until the load is less than the desirable load
final Iterator<Group> iterator = groupAllocationTable.getValue(eventProcessor).iterator();
while (load > desirableLoad && iterator.hasNext()) {
final Group group = iterator.next();
items.add(group);
load -= group.getLoad();
}
}
// Put the bin with the size
bins.put(eventProcessor, desirableLoad - load);
}
return new Tuple<>(bins, items);
}
use of edu.snu.mist.core.task.groupaware.eventprocessor.EventProcessor in project mist by snuspl.
the class FirstFitRebalancerImpl method triggerRebalancing.
@Override
public void triggerRebalancing() {
final List<EventProcessor> eventProcessors = groupAllocationTable.getEventProcessorsNotRunningIsolatedGroup();
// Calculate each load and total load
final Map<EventProcessor, Double> loadTable = new HashMap<>();
double totalLoad = 0.0;
for (final EventProcessor eventProcessor : eventProcessors) {
final double load = eventProcessor.getLoad();
totalLoad += load;
eventProcessor.setLoad(load);
loadTable.put(eventProcessor, load);
}
// Desirable load
// Each event processor should has the load evenly
final double desirableLoad = totalLoad * (1.0 / eventProcessors.size());
// Make bins and items.
final Tuple<Map<EventProcessor, Double>, List<Group>> binsAndItems = makeBinsAndItems(desirableLoad, loadTable, eventProcessors);
// First-fit heuristic algorithm
final Map<Group, EventProcessor> mapping = firstFitHeuristic(eventProcessors, binsAndItems.getKey(), binsAndItems.getValue());
// Reassign the groups to the event processor
for (final EventProcessor eventProcessor : eventProcessors) {
final Iterator<Group> iterator = groupAllocationTable.getValue(eventProcessor).iterator();
while (iterator.hasNext()) {
final Group group = iterator.next();
final EventProcessor destEP = mapping.remove(group);
if (destEP != null) {
iterator.remove();
final Collection<Group> dest = groupAllocationTable.getValue(destEP);
dest.add(group);
}
}
}
if (LOG.isLoggable(Level.FINE)) {
final Map<EventProcessor, Double> afterRebalancingLoadTable = new HashMap<>();
for (final EventProcessor ep : groupAllocationTable.getKeys()) {
afterRebalancingLoadTable.put(ep, calculateLoadOfGroupsForLogging(groupAllocationTable.getValue(ep)));
}
LOG.log(Level.FINE, "Rebalanacing Groups (Desirable load={0}) \n" + "=========== Before LB ==========\n {1} \n" + "=========== After LB ==========\n {2} \n", new Object[] { desirableLoad, printMap(loadTable), printMap(afterRebalancingLoadTable) });
}
}
use of edu.snu.mist.core.task.groupaware.eventprocessor.EventProcessor in project mist by snuspl.
the class DefaultTaskStatsUpdater method updateTaskStatsToMaster.
@Override
public void updateTaskStatsToMaster(final GroupAllocationTable groupAllocationTable) throws AvroRemoteException {
final List<EventProcessor> epList = new ArrayList<>(groupAllocationTable.getKeys());
final int numEventProcessors = epList.size();
final List<Group> groupList = new ArrayList<>();
// Get the whole group list.
for (final EventProcessor ep : epList) {
groupList.addAll(groupAllocationTable.getValue(ep));
}
double totalLoad = 0.0;
final Map<String, GroupStats> groupStatsMap = new HashMap<>();
for (final Group group : groupList) {
groupStatsMap.put(group.getGroupId(), GroupStats.newBuilder().setGroupLoad(group.getLoad()).setAppId(group.getApplicationInfo().getApplicationId()).setGroupQueryNum(group.getQueries().size()).setGroupId(group.getGroupId()).build());
totalLoad += group.getLoad();
}
final double taskCpuLoad = totalLoad / numEventProcessors;
proxyToMaster.updateTaskStats(taskId, TaskStats.newBuilder().setTaskLoad(taskCpuLoad).setGroupStatsMap(groupStatsMap).build());
}
use of edu.snu.mist.core.task.groupaware.eventprocessor.EventProcessor in project mist by snuspl.
the class DefaultGroupRebalancerImpl method triggerRebalancing.
@Override
public void triggerRebalancing() {
LOG.info("REBALANCING START");
long rebalanceStart = System.currentTimeMillis();
try {
// Skip if it is an isolated processor that runs an isolated group
final List<EventProcessor> eventProcessors = groupAllocationTable.getEventProcessorsNotRunningIsolatedGroup();
// Overloaded threads
final List<EventProcessor> overloadedThreads = new LinkedList<>();
// Underloaded threads
final PriorityQueue<EventProcessor> underloadedThreads = new PriorityQueue<>(new Comparator<EventProcessor>() {
@Override
public int compare(final EventProcessor o1, final EventProcessor o2) {
final Double load1 = o1.getLoad();
final Double load2 = o2.getLoad();
return load1.compareTo(load2);
}
});
// Calculate each load and total load
for (final EventProcessor eventProcessor : eventProcessors) {
final double load = eventProcessor.getLoad();
if (load > beta) {
overloadedThreads.add(eventProcessor);
} else if (load < alpha) {
underloadedThreads.add(eventProcessor);
}
}
// LOGGING
// logging(eventProcessors, loadTable);
double targetLoad = (alpha + beta) / 2;
int rebNum = 0;
Collections.sort(overloadedThreads, new Comparator<EventProcessor>() {
@Override
public int compare(final EventProcessor o1, final EventProcessor o2) {
return o1.getLoad() < o2.getLoad() ? 1 : -1;
}
});
if (!overloadedThreads.isEmpty() && !underloadedThreads.isEmpty()) {
for (final EventProcessor highLoadThread : overloadedThreads) {
final Collection<Group> highLoadGroups = groupAllocationTable.getValue(highLoadThread);
final List<Group> sortedHighLoadGroups = new LinkedList<>(highLoadGroups);
Collections.sort(sortedHighLoadGroups, new Comparator<Group>() {
@Override
public int compare(final Group o1, final Group o2) {
if (o1.getLoad() < o2.getLoad()) {
return -1;
} else if (o1.getLoad() > o2.getLoad()) {
return 1;
} else {
return 0;
}
}
});
for (final Group highLoadGroup : sortedHighLoadGroups) {
// do not move a group if it is already moved before GROUP_PINNING_TIME
if (System.currentTimeMillis() - highLoadGroup.getLatestMovedTime() >= TimeUnit.SECONDS.toMillis(groupPinningTime)) {
final double groupLoad = highLoadGroup.getLoad();
// Just rebalance
if (!highLoadGroup.isSplited()) {
if (highLoadThread.getLoad() - groupLoad >= targetLoad) {
final EventProcessor peek = underloadedThreads.peek();
if (peek.getLoad() + groupLoad <= targetLoad) {
final EventProcessor lowLoadThread = underloadedThreads.poll();
moveGroup(highLoadGroup, highLoadGroups, highLoadThread, lowLoadThread, underloadedThreads);
rebNum += 1;
highLoadGroup.setLatestMovedTime(System.currentTimeMillis());
// Prevent lots of groups from being reassigned
if (rebNum >= TimeUnit.MILLISECONDS.toSeconds(rebalancingPeriod)) {
break;
}
}
}
} else {
// Merge splitted group
// 1. find the thread that has the lowest load among threads that hold the splitted groups
final Group lowLoadGroup = findLowestLoadThreadSplittedGroup(highLoadGroup);
// 2. Check we can move the high load group to the low load thread group
if (lowLoadGroup != null && lowLoadGroup != highLoadGroup && highLoadGroup.getEventProcessor().getLoad() - groupLoad >= targetLoad && lowLoadGroup.getEventProcessor().getLoad() + groupLoad <= targetLoad) {
// 3. merge!
if (merge(highLoadGroup, highLoadGroups, highLoadThread, lowLoadGroup)) {
rebNum += 1;
highLoadGroups.remove(highLoadGroup);
}
// Prevent lots of groups from being reassigned
if (rebNum >= TimeUnit.MILLISECONDS.toSeconds(rebalancingPeriod)) {
break;
}
}
}
}
}
// Prevent lots of groups from being reassigned
if (rebNum >= TimeUnit.MILLISECONDS.toSeconds(rebalancingPeriod)) {
break;
}
}
}
long rebalanceEnd = System.currentTimeMillis();
LOG.log(Level.INFO, "Rebalancing number: {0}, elapsed time: {1}", new Object[] { rebNum, rebalanceEnd - rebalanceStart });
// LOG.log(Level.INFO, "-------------TABLE-------------\n{0}",
// new Object[]{groupAllocationTable.toString()});
} catch (final Exception e) {
LOG.log(Level.WARNING, "Exception " + e);
e.printStackTrace();
throw new RuntimeException(e);
}
}
use of edu.snu.mist.core.task.groupaware.eventprocessor.EventProcessor in project mist by snuspl.
the class FirstFitRebalancerImpl method firstFitHeuristic.
private Map<Group, EventProcessor> firstFitHeuristic(final List<EventProcessor> eventProcessors, final Map<EventProcessor, Double> bins, final List<Group> items) {
final Map<Group, EventProcessor> mapping = new HashMap<>(items.size());
final Iterator<Group> iterator = items.iterator();
while (iterator.hasNext()) {
final Group item = iterator.next();
// find the first bin that can hold the item
for (final EventProcessor eventProcessor : eventProcessors) {
final double size = bins.get(eventProcessor);
final double itemSize = item.getLoad();
if (size >= itemSize) {
// This is the first bin that can hold the item!
iterator.remove();
mapping.put(item, eventProcessor);
bins.put(eventProcessor, size - itemSize);
break;
}
}
}
if (!items.isEmpty()) {
// Second
final Iterator<Group> secondIter = items.iterator();
while (secondIter.hasNext()) {
final Group item = secondIter.next();
// find the first bin that can hold the item
for (final EventProcessor eventProcessor : eventProcessors) {
final double size = bins.get(eventProcessor);
final double itemSize = item.getLoad();
if (size > 0) {
// This is the first bin that can hold the item!
secondIter.remove();
mapping.put(item, eventProcessor);
bins.put(eventProcessor, size - itemSize);
break;
}
}
}
}
if (!items.isEmpty()) {
throw new RuntimeException("First-fit algorithm is incorrect");
}
return mapping;
}
Aggregations