1function [W, rho_total] = qsys_mg1_psjf(lambda, mu, cs)
2% QSYS_MG1_PSJF Compute mean response time
for M/G/1/PSJF queue
4% [W, RHO] = QSYS_MG1_PSJF(LAMBDA, MU, CS) computes the mean response time
5%
for each job
class in an M/G/1 queue with Preemptive Shortest Job First
8% Under PSJF, priority
is based on a job
's original size (not remaining size).
9% Jobs with smaller original sizes always preempt jobs with larger sizes.
11% For PSJF, the mean response time for a job of size x is given by
12% (Section 3.2 of Wierman-Harchol-Balter 2003):
14% E[T(x)]^PSJF = (lambda * integral_0^x t^2*f(t)dt) / (2*(1-rho(x))^2)
18% - rho(x) = lambda * integral_0^x t*f(t)dt (truncated load)
19% - f(t) is the service time density (mixture of exponentials)
21% For exponential service, the expected response time for class k is computed
22% by integrating E[T(x)] over the exponential distribution of class k sizes.
24% CLASSIFICATION (Wierman-Harchol-Balter 2003):
25% PSJF is "Always Unfair" - some job size is treated unfairly under all
26% loads and all service distributions.
29% lambda : Vector of arrival rates per class
30% mu : Vector of service rates per class
31% cs : Vector of coefficients of variation per class (cs=1 for exponential)
34% W : Vector of mean response times per class
35% rho : Overall system utilization (modified for Little's law)
38% - A. Wierman and M. Harchol-Balter,
"Classifying scheduling policies with
39% respect to unfairness in an M/GI/1", SIGMETRICS 2003, Section 3.2.
40% - L. Kleinrock,
"Queueing Systems, Volume II: Computer Applications",
43% Copyright (c) 2012-2026, Imperial College London
46% Ensure inputs are column vectors
47lambda = reshape(lambda, [], 1);
48mu = reshape(mu, [], 1);
49cs = reshape(cs, [], 1);
51% Validate input lengths
52if ~isequal(length(lambda), length(mu), length(cs))
53 error(
'qsys_mg1_psjf:InvalidInput', ...
54 'lambda, mu, and cs must have the same length');
57% Validate positive values
58if any(lambda <= 0) || any(mu <= 0) || any(cs < 0)
59 error('qsys_mg1_psjf:InvalidInput', ...
60 'lambda and mu must be positive, cs must be non-negative');
66rho_total = sum(lambda ./ mu);
70 error('qsys_mg1_psjf:UnstableSystem', ...
71 sprintf('System
is unstable: utilization rho = %g >= 1', rho_total));
74% Check if all
classes are exponential (cs = 1)
75if all(abs(cs - 1) < 1e-6)
76 % Use specialized formula for exponential service
77 W = qsys_mg1_psjf_exp(lambda, mu);
79 % General case: use numerical integration
80 W = qsys_mg1_psjf_general(lambda, mu, cs);
83% Compute rhohat = Q/(1+Q) to match qsys convention
85rho_total = Q / (1 + Q);
89function W = qsys_mg1_psjf_exp(lambda, mu)
90% Specialized PSJF formula for exponential service times
92% For exponential service, we integrate E[T(x)] over the exponential
93% distribution of job sizes. The service time mixture PDF
is:
94% f(t) = sum_i (lambda_i/lambda_total) * mu_i * exp(-mu_i * t)
96% The expected response time for class k
is:
97% E[T_k] = integral_0^inf E[T(x)] * f_k(x) dx
99% where f_k(x) = mu_k * exp(-mu_k * x) and
100% E[T(x)] = x/(1-rho(x)) + m2(x)/(2*(1-rho(x))^2)
103lambda_total = sum(lambda);
104p = lambda / lambda_total; % mixing probabilities
109 % Integrate E[T(x)] * f_k(x) from 0 to infinity
110 % Use numerical integration with appropriate upper limit
113 % Upper limit: 20 mean service times covers 99.9999998% of exponential
116 % Response time function for a job of size x
117 T_of_x = @(x) compute_psjf_response(x, lambda, mu, p, lambda_total);
119 % Exponential density for class k
120 f_k = @(x) mu_k * exp(-mu_k * x);
122 % Integrand: E[T(x)] * f_k(x)
123 integrand = @(x) T_of_x(x) .* f_k(x);
125 % Numerical integration
126 W(k) = integral(integrand, 0, x_max, 'RelTol', 1e-8, 'AbsTol', 1e-10);
131function T = compute_psjf_response(x, lambda, mu, p, lambda_total)
132% Compute PSJF response time E[T(x)] for a job of size x
134% E[T(x)] = x/(1-rho(x)) + m2(x)/(2*(1-rho(x))^2)
137% rho(x) = lambda * integral_0^x t * f(t) dt
138% m2(x) = lambda * integral_0^x t^2 * f(t) dt
140% For mixture of exponentials:
141% integral_0^x t * mu_i * exp(-mu_i*t) dt = 1/mu_i - (1/mu_i + x)*exp(-mu_i*x)
142% integral_0^x t^2 * mu_i * exp(-mu_i*t) dt = 2/mu_i^2 - (2/mu_i^2 + 2x/mu_i + x^2)*exp(-mu_i*x)
152 % Compute truncated first moment: integral_0^x t * f(t) dt
156 % integral_0^x t * mu_i * exp(-mu_i*t) dt
157 int_t = 1/mu_i - (1/mu_i + xj) * exp(-mu_i * xj);
158 m1_x = m1_x + p(i) * int_t;
162 rho_x = lambda_total * m1_x;
164 % Compute truncated second moment: integral_0^x t^2 * f(t) dt
168 % integral_0^x t^2 * mu_i * exp(-mu_i*t) dt
169 int_t2 = 2/mu_i^2 - (2/mu_i^2 + 2*xj/mu_i + xj^2) * exp(-mu_i * xj);
170 m2_x = m2_x + p(i) * int_t2;
173 % Scale by lambda_total for m2 term
174 m2_x_scaled = lambda_total * m2_x;
176 % PSJF response time formula
180 T(j) = xj / (1 - rho_x) + m2_x_scaled / (2 * (1 - rho_x)^2);
186function W = qsys_mg1_psjf_general(lambda, mu, cs)
187% General PSJF formula for non-exponential service (numerical integration)
188% Uses Gamma approximation for service time distributions
191lambda_total = sum(lambda);
193% For non-exponential, use class-based approximation (original formula)
194% with numerical correction for variance
196mean_service = 1 ./ mu;
197[~, sort_idx] = sort(mean_service, 'ascend');
199lambda_sorted = lambda(sort_idx);
200mu_sorted = mu(sort_idx);
201cs_sorted = cs(sort_idx);
203rho_i = lambda_sorted ./ mu_sorted;
205W_sorted = zeros(K, 1);
208 x = 1 / mu_sorted(k);
209 rho_x = sum(rho_i(1:k));
213 E_S2_i = (1 + cs_sorted(i)^2) / mu_sorted(i)^2;
214 m2_x = m2_x + lambda_sorted(i) * E_S2_i;
220 waiting_term = m2_x / (2 * (1 - rho_x)^2);
221 service_term = x / (1 - rho_x);
222 W_sorted(k) = waiting_term + service_term;
226[~, unsort_idx] = sort(sort_idx);
227W = W_sorted(unsort_idx);