func startNextJob(event *models.Event, node *models.Node, job *models.Job, scheduler scheduling.Scheduler, eventQueue *models.EventQueue) { node.CurJob = job node.EstCompletion = event.Time + scheduler.GetAllocation(job) completeTime := event.Time + job.RealExec if job.AbsoluteDeadline() < node.EstCompletion && job.AbsoluteDeadline() < completeTime { heap.Push(eventQueue, &models.Event{ Job: job, Time: job.AbsoluteDeadline(), Node: node, Type: models.Miss, }) } else if node.EstCompletion < completeTime { heap.Push(eventQueue, &models.Event{ Job: job, Time: node.EstCompletion, Node: node, Type: models.Stretch, }) } else { heap.Push(eventQueue, &models.Event{ Job: event.Job, Time: completeTime, Node: node, Type: models.Complete, }) } }
// GenJobs generates and returns a slice of Jobs with timings // derived from exponentially distributed random variables. func GenJobs(sysLoad float64, simTime int, clusterSize int, outPath string, stats chan string, precision chan float64, threadCap *models.Semaphore, jobPool *sync.Pool) { threadCap.Lock() var totalComputation = 0 var numJobs = round( (sysLoad * float64(simTime) * float64(clusterSize)) / realExecAvg) var numSubmitters = round(math.Sqrt(float64(numJobs))) submitterEstAvgs := make([]float64, numSubmitters) for i := 0; i < numSubmitters; i++ { for { submitterEstAvgs[i] = rand.ExpFloat64() * estExecAvg if submitterEstAvgs[i] > estExecAvg/15.0 && submitterEstAvgs[i] < estExecAvg*15.0 { break } } } var burstSize int var burstAvg = sysLoad * float64(clusterSize) * burstMult var interval int var intervalLambda = float64(simTime) / (float64(numJobs) / burstAvg) var jobs []models.Job var arrival = 0 var estExec, realExec, deadline, submitter int for i := 0; i < numJobs; { submitter = rand.Intn(numSubmitters) if i != 0 { interval = round(rand.ExpFloat64() * float64(intervalLambda)) arrival += interval } burstSize = round(rand.ExpFloat64() * burstAvg) for j := 0; j < burstSize; j++ { realExec = round(rand.ExpFloat64() * realExecAvg) for { // estExec must always be > realExec estExec = round(rand.ExpFloat64() * submitterEstAvgs[submitter]) if estExec > realExec { break } } for { // deadline must always be > estExec (n.b. this implicitly makes it > realExec) deadline = round(rand.ExpFloat64() * deadlineAvg) if deadline > estExec { break } } var newJob *models.Job poolFetch := jobPool.Get() if poolFetch == nil { newJob = &models.Job{} } else { newJob = poolFetch.(*models.Job) } newJob.ID = i newJob.SubmitterID = submitter newJob.Arrival = arrival newJob.EstExec = estExec newJob.RealExec = realExec newJob.Deadline = deadline jobs = append(jobs, *newJob) jobPool.Put(newJob) totalComputation += realExec i++ } } WriteJobsToCSV(jobs, outPath) var trueLoad = (float64(totalComputation) / (float64(simTime) * float64(clusterSize))) precision <- (trueLoad / sysLoad) var statsMsg = "Generated jobs for:\n" + " Cluster Size: %v\n" + " System Load: %v\n" + " Time Span: %v\n" + " Actual computation load: %v\n" statsMsg = fmt.Sprintf(statsMsg, clusterSize, sysLoad, simTime, trueLoad) stats <- statsMsg threadCap.Free() }