Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable preemption of jobs in a queue #71

Closed
wants to merge 8 commits into from
Closed

Enable preemption of jobs in a queue #71

wants to merge 8 commits into from

Conversation

hdavid16
Copy link
Member

@hdavid16 hdavid16 commented Apr 16, 2021

Preemption can be done on a Store object if an item of higher priority arrives. The amount of time the preempted object was served is stored.

This change adds a method to put that requires that the item have the following fields:

  • :priority::Int: Integer specifying the priority of that item (the more
    negative, the higher the priority).
  • :process::Process: The storage process
    of the item. This is used to know which Process to
    interrupt when preempting.

This addresses #61

See example below:

using ResumableFunctions, SimJulia

#Define Job (item) to send to the queue (Store)
abstract type AbstractJob end
mutable struct Job <: AbstractJob
    id::Int
    arrival::Number
    priority::Int
    start_service::Number
    time_in_service::Number
    process::Union{Missing, SimJulia.Process}
    size::Number
end

#define a function to serve jobs that arrive at a queue and allow preemption
@resumable function serve(env, server, job)
    @yield timeout(env, job.arrival) #job arrives
    println("job $(job.id) enters queue at t = $(now(env))")
    while true
        try
            @yield put(server, job, true) #add job to queue, allow preemption
            println("Starting service on job $(job.id) at t = $(now(env)).")
            job.start_service = now(env) #save time service started on job
            @yield timeout(env, job.size - job.time_in_service) #service duration excludes any time already spent in service (if preempted)
            println("Service complete on job $(job.id) at t = $(now(env)).")
            job.time_in_service = now(env) - job.start_service #update time in serice
            get(server, x -> x.id == job.id) #remove job from queue
            break
        catch exc
            pre = exc.cause #find cause of preemption
            job.time_in_service = now(env) - job.start_service #update time in service
            println("Service on job $(job.id) interrupted (preempted) by job $(pre.id) at t = $(now(env)).")
        end
    end
end

#create simulation
sim = Simulation() #simulation object
server = Store{Job}(sim, capacity = UInt(1)) #server that processes jobs
job1 = Job(1,0,-1,0,0,missing,3) #add 3 jobs
job2 = Job(2,1,0,0,0,missing,3)
job3 = Job(3,2,-2,0,0,missing,3)

#create and store service processes
job1.process = @process serve(sim, server, job1)
job2.process = @process serve(sim, server, job2)
job3.process = @process serve(sim, server, job3)

#run simulation
run(sim)

#output
#=
job 1 enters queue at t = 0.0
Starting service on job 1 at t = 0.0.
job 2 enters queue at t = 1.0
job 3 enters queue at t = 2.0
Service on job 1 interrupted (preempted) by job 3 at t = 2.0.
Starting service on job 3 at t = 2.0.
Service complete on job 3 at t = 5.0.
Starting service on job 1 at t = 5.0.
Service complete on job 1 at t = 6.0.
Starting service on job 2 at t = 6.0.
Service complete on job 2 at t = 9.0.
=#

@hdavid16 hdavid16 closed this May 22, 2021
@Krastanov
Copy link
Member

@hdavid16 , should we consider reopening this pull request (or creating a new one if that is easier)?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants