Beispiel #1
0
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,
		})
	}
}
Beispiel #2
0
// SimulateFromFile runs a simulation for a single specified batch of jobs and appends the results to a
// specified file in CSV format
func SimulateFromFile(
	clusterSize int, sysLoad int, inputPath string, outputPath string,
	outputLock *sync.Mutex, threadCapper *models.Semaphore,
	waitGroup *sync.WaitGroup, schedulerType int) {

	threadCapper.Lock()

	jobs := utils.ReadJobs(inputPath)

	eventQueue := make(models.EventQueue, len(jobs))
	for i := 0; i < len(jobs); i++ {
		job := jobs[i]
		event := models.Event{
			Time: job.Arrival,
			Job:  &job,
			Type: models.Arrival,
		}
		eventQueue[i] = &event
	}
	heap.Init(&eventQueue)

	nodeQueue := make(models.NodeQueue, clusterSize)
	for i := 0; i < clusterSize; i++ {
		node := models.Node{
			CurJob:        nil,
			EstCompletion: -1,
			Index:         i,
		}
		nodeQueue[i] = &node
	}

	jobQueue := make(models.JobQueue, 0)

	var scheduler scheduling.Scheduler
	switch schedulerType {
	case Markov:
		scheduler = &scheduling.MarkovScheduler{
			QueuedJobs:   &jobQueue,
			Nodes:        &nodeQueue,
			ScheduleSize: clusterSize * 384,
		}
	case StandardEDF:
		scheduler = &scheduling.StandardEDFScheduler{
			QueuedJobs: &jobQueue,
			Nodes:      &nodeQueue,
		}
	case OmniscientEDF:
		scheduler = &scheduling.OmniscientEDFScheduler{
			QueuedJobs: &jobQueue,
			Nodes:      &nodeQueue,
		}
	}
	scheduler.Init()

	jobsSeen, jobsRejected, jobsCompleted, jobsKilled, jobsDlMissed := 0, 0, 0, 0, 0
	for eventQueue.Len() > 0 {
		event := heap.Pop(&eventQueue).(*models.Event)
		switch event.Type {
		case models.Arrival:
			jobsSeen++
			if scheduler.IsJobAdmitted(event.Job) {
				node := heap.Pop(&nodeQueue).(*models.Node)
				if node.CurJob == nil { // Start job right away if there's a Node waiting
					startNextJob(event, node, heap.Pop(&jobQueue).(*models.Job), scheduler, &eventQueue)
				}
				// Completion events from other Jobs will automatically start the next Job for us if
				// no nodes are ready now
				heap.Push(&nodeQueue, node)
			} else { // !IsJobAdmitted
				jobsRejected++
			}

		case models.Stretch:
			event.Node.EstCompletion += scheduler.GetAllowance()
			heap.Fix(&nodeQueue, event.Node.Index)
			if scheduler.GetAllocation(event.Job)+scheduler.GetAllowance() >= event.Job.RealExec {
				heap.Push(&eventQueue, &models.Event{
					Job:  event.Job,
					Time: event.Time + event.Job.RealExec - scheduler.GetAllocation(event.Job),
					Node: event.Node,
					Type: models.Complete,
				})
			} else {
				heap.Push(&eventQueue, &models.Event{
					Job:  event.Job,
					Time: event.Node.EstCompletion,
					Node: event.Node,
					Type: models.Kill,
				})
			}
			scheduler.DeductAllowance()

		case models.Complete:
			jobsCompleted++
			scheduler.SuccessCallback(event.Job)
			if jobQueue.Len() > 0 {
				startNextJob(event, event.Node, heap.Pop(&jobQueue).(*models.Job), scheduler, &eventQueue)
			} else {
				event.Node.CurJob = nil
				event.Node.EstCompletion = -1
			}
			heap.Fix(&nodeQueue, event.Node.Index)

		case models.Kill:
			jobsKilled++
			scheduler.FailCallback(event.Job)
			if jobQueue.Len() > 0 {
				startNextJob(event, event.Node, heap.Pop(&jobQueue).(*models.Job), scheduler, &eventQueue)
			} else {
				event.Node.CurJob = nil
				event.Node.EstCompletion = -1
			}
			heap.Fix(&nodeQueue, event.Node.Index)

		case models.Miss:
			jobsDlMissed++
			scheduler.FailCallback(event.Job)
			if jobQueue.Len() > 0 {
				startNextJob(event, event.Node, heap.Pop(&jobQueue).(*models.Job), scheduler, &eventQueue)
			} else {
				event.Node.CurJob = nil
				event.Node.EstCompletion = -1
			}
			heap.Fix(&nodeQueue, event.Node.Index)
		}
	}

	outputLock.Lock()
	var record = []string{
		fmt.Sprintf("%d", clusterSize),
		fmt.Sprintf("%d", sysLoad),
		fmt.Sprintf("%d", jobsSeen),
		fmt.Sprintf("%d", jobsCompleted),
		fmt.Sprintf("%d", jobsRejected),
		fmt.Sprintf("%d", jobsKilled),
		fmt.Sprintf("%d", jobsDlMissed),
	}
	file, err := os.OpenFile(outputPath, os.O_APPEND|os.O_WRONLY, 0666)
	utils.Check(err)
	writer := csv.NewWriter(file)
	err = writer.Write(record)
	utils.Check(err)
	writer.Flush()
	if writer.Error() != nil {
		fmt.Println(writer.Error())
	} else {
		file.Sync()
	}
	file.Close()
	outputLock.Unlock()
	threadCapper.Free()
	waitGroup.Done()
}