Created
February 10, 2014 22:05
-
-
Save mschoch/8925204 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package workload | |
| import ( | |
| "math/rand" | |
| "time" | |
| ) | |
| type Schedule []time.Duration | |
| type ScheduleBuilder struct { | |
| schedules []Schedule | |
| lastOffTime []time.Duration | |
| lastOnTime []time.Duration | |
| numUsers int | |
| maxActive int | |
| rampOffset time.Duration | |
| minOfflineDuration time.Duration | |
| maxOfflineDuration time.Duration | |
| totalDuration time.Duration | |
| } | |
| func NewScheduleBuilder(numUsers, maxActive int, rampOffset time.Duration, minOfflineDuration, maxOfflineDuration, totalDuration time.Duration) *ScheduleBuilder { | |
| return &ScheduleBuilder{ | |
| schedules: make([]Schedule, numUsers), | |
| lastOffTime: make([]time.Duration, numUsers), | |
| lastOnTime: make([]time.Duration, numUsers), | |
| numUsers: numUsers, | |
| maxActive: maxActive, | |
| rampOffset: rampOffset, | |
| minOfflineDuration: minOfflineDuration, | |
| maxOfflineDuration: maxOfflineDuration, | |
| totalDuration: totalDuration, | |
| } | |
| } | |
| func (sb *ScheduleBuilder) BuildSchedule() []Schedule { | |
| // initially everyone is offline | |
| sb.init() | |
| // schedule the initial ramp up | |
| sb.rampUp() | |
| // look for offline duration violations | |
| violator := sb.findNextOfflineViolation() | |
| for violator != -1 { | |
| // if we find an offline violation, we need to turn that user on | |
| // compute random off duration | |
| offDuration := time.Duration(rand.Float64()*float64(sb.maxOfflineDuration-sb.minOfflineDuration)) + sb.minOfflineDuration | |
| transitionTime := sb.lastOffTime[violator] + offDuration | |
| sb.turnOnUser(violator, transitionTime) | |
| // now that we have turned on an additional user, we should have to many users on at once | |
| // find user thats been on the longest and turn them off at the same time | |
| longestOn := sb.findUserOnLongest() | |
| sb.turnOffUser(longestOn, transitionTime) | |
| } | |
| return sb.schedules | |
| } | |
| func (sb *ScheduleBuilder) init() { | |
| for i := 0; i < sb.numUsers; i++ { | |
| sb.schedules[i] = make(Schedule, 0) | |
| sb.lastOffTime[i] = 0 | |
| sb.lastOnTime[i] = 0 | |
| } | |
| } | |
| func (sb *ScheduleBuilder) rampUp() { | |
| var durationIterator time.Duration | |
| for i := 0; i < sb.maxActive; i++ { | |
| sb.turnOnUser(i, durationIterator) | |
| durationIterator += sb.rampOffset | |
| } | |
| } | |
| func (sb *ScheduleBuilder) turnOnUser(index int, at time.Duration) { | |
| sb.schedules[index] = append(sb.schedules[index], at) | |
| sb.lastOnTime[index] = at | |
| } | |
| func (sb *ScheduleBuilder) turnOffUser(index int, at time.Duration) { | |
| sb.schedules[index] = append(sb.schedules[index], at) | |
| sb.lastOffTime[index] = at | |
| } | |
| func (sb *ScheduleBuilder) isUserOn(index int) bool { | |
| if sb.lastOnTime[index] > sb.lastOffTime[index] { | |
| return true | |
| } | |
| return false | |
| } | |
| func (sb *ScheduleBuilder) isUserOff(index int) bool { | |
| if sb.lastOnTime[index] < sb.lastOffTime[index] { | |
| return true | |
| } | |
| return false | |
| } | |
| func (sb *ScheduleBuilder) lastOfflineDuration(index int) time.Duration { | |
| return sb.totalDuration - sb.lastOffTime[index] | |
| } | |
| func (sb *ScheduleBuilder) findNextOfflineViolation() int { | |
| rv := -1 | |
| for i := 0; i < sb.numUsers; i++ { | |
| // if the user is offline and their offline duration would exceed | |
| // the max if they never go back online, return this user as violation | |
| if sb.isUserOff(i) && sb.lastOfflineDuration(i) > sb.maxOfflineDuration { | |
| return i | |
| } | |
| } | |
| // otherwise -1 to indicate no violation | |
| return rv | |
| } | |
| func (sb *ScheduleBuilder) findUserOnLongest() int { | |
| var longestTime time.Duration | |
| longestIndex := -1 | |
| for i := 0; i < sb.numUsers; i++ { | |
| if sb.isUserOn(i) { | |
| userOnTime := sb.totalDuration - sb.lastOnTime[i] | |
| if userOnTime > longestTime { | |
| // new highest | |
| longestTime = userOnTime | |
| longestIndex = i | |
| } | |
| } | |
| } | |
| return longestIndex | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment