use of edu.snu.mist.core.task.groupaware.Group 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.Group 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.Group in project mist by snuspl.
the class UtilizationLoadUpdater method updateGroupAndThreadLoad.
/**
* Update the load of the event processor and the assigned groups.
* @param eventProcessor event processor
* @param groups assigned groups
*/
private void updateGroupAndThreadLoad(final EventProcessor eventProcessor, final Collection<Group> groups) {
// boolean isOverloaded = false;
double eventProcessorLoad = 0.0;
final long elapsedTime = startTime - previousUpdateTime;
final List<Group> skipGroups = new LinkedList<>();
for (final Group group : groups) {
double load = 0.0;
final List<Query> queries = group.getQueries();
final long processingEvent = group.getProcessingEvent().get();
group.getProcessingEvent().addAndGet(-processingEvent);
final long incomingEvent = processingEvent + group.numberOfRemainingEvents();
final long processingEventTime = group.getProcessingTime().get();
group.getProcessingTime().addAndGet(-processingEventTime);
if (LOG.isLoggable(Level.FINE)) {
LOG.log(Level.FINE, "Group {0}, ProcessingEvent: {1}, IncomingEvent: {2}, ProcessingTime: {3}", new Object[] { group.getGroupId(), processingEvent, incomingEvent, processingEventTime });
}
// Just use the previous load
if (processingEventTime == 0 && incomingEvent != 0) {
// isOverloaded = true;
load = group.getLoad();
} else if (incomingEvent == 0) {
// No incoming event
load = defaultGroupLoad;
} else {
// processed event, incoming event
final double inputRate = (incomingEvent * 1000) / (double) elapsedTime;
final double processingRate = (processingEvent * NS_UNIT) / (double) processingEventTime;
if (processingEvent == 0 || processingRate == 0) {
load = (1 * NS_UNIT) / (double) processingEventTime;
} else {
final double groupLoad = Math.min(1.5, inputRate / processingRate);
load = groupLoad;
}
if (LOG.isLoggable(Level.FINE)) {
LOG.log(Level.FINE, "Group {0}, InputRate: {1}, ProcessingRate: {2}, GroupLoad: {3}", new Object[] { group.getGroupId(), inputRate, processingRate, load });
}
}
eventProcessorLoad += load;
group.setLoad(load);
// Calculate query load based on the group load!
for (final Query query : queries) {
// Number of processed events
final long queryProcessingEvent = query.getProcessingEvent().get();
query.getProcessingEvent().getAndAdd(-queryProcessingEvent);
final long incomingE = query.numberOfRemainingEvents();
final long queryIncomingEvent = incomingE + queryProcessingEvent;
if (incomingEvent == 0) {
query.setLoad(0);
} else {
query.setLoad(load * (queryIncomingEvent / (double) incomingEvent));
}
}
}
eventProcessor.setLoad(eventProcessorLoad);
// Overloaded!
/*
if (isOverloaded) {
eventProcessor.setLoad(1.0);
// distribute the load
final int size = groups.size();
final double balancedLoad = 1.0 / size;
for (final Group group : groups) {
group.setLoad(balancedLoad);
final int querySize = group.getQueries().size();
final double queryLoad = balancedLoad / querySize;
for (final Query query : group.getQueries()) {
query.setLoad(queryLoad);
}
}
} else {
eventProcessor.setLoad(eventProcessorLoad);
}
*/
}
use of edu.snu.mist.core.task.groupaware.Group in project mist by snuspl.
the class DefaultGroupMergerImpl method logging.
private void logging(final List<EventProcessor> eventProcessors, final Map<EventProcessor, Double> loadTable) {
final StringBuilder sb = new StringBuilder();
sb.append("-------------- TABLE ----------------\n");
for (final EventProcessor ep : eventProcessors) {
final Collection<Group> groups = groupAllocationTable.getValue(ep);
sb.append(ep);
sb.append(" -> [");
sb.append(loadTable.get(ep));
sb.append("], [");
sb.append(groups.size());
sb.append("], ");
sb.append(groups);
sb.append("\n");
}
LOG.info(sb.toString());
}
use of edu.snu.mist.core.task.groupaware.Group 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.isSplited() && !o2.isSplited()) {
return -1;
} else if (!o1.isSplited() && o2.isSplited()) {
return 1;
} else {
if (o1.getLoad() < o2.getLoad()) {
return -1;
} else {
return 1;
}
}
}
});
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();
if (!highLoadGroup.isSplited()) {
// Rebalance!!!
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;
}
}
}
}
}
}
// 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);
}
}
Aggregations