1function [PercRT, PercTable] = getPerctRespT(self, percentiles,
jobclass, method)
2% [PERCRT, PERCTABLE] = GETPERCTRESPT(SELF, PERCENTILES, JOBCLASS)
3% Retrieve response time percentile results from FJ_codes analysis or CDF
6% self - SolverMAM instance
7% percentiles - Array of percentile values to compute (e.g., [0.90, 0.95, 0.99] or [90, 95, 99])
8%
jobclass - (optional) specific job
class to retrieve percentiles
for
11% PercRT - Struct array with fields for each class:
13% .percentiles - percentile levels (e.g., [90, 95, 99])
14% .values - percentile values (response times)
15% .K - number of parallel queues in Fork-Join
16% PercTable - Formatted table for display with columns:
17% JobClass, Percentile, ResponseTime
20% Z. Qiu, J.F. Pérez, and
P. Harrison,
"Beyond the Mean in Fork-Join Queues:
21% Efficient Approximation for Response-Time Tails", IFIP Performance 2015.
22% Copyright 2015 Imperial College London
24% Copyright (c) 2012-2026, Imperial College London
27% The forktail method
is topology-driven, not solver-specific: hand it back
28% to the base implementation rather than duplicating it here.
29if nargin >= 4 && ~isempty(method) && ~strcmpi(method,
'default')
33 [PercRT, PercTable] = getPerctRespT@NetworkSolver(self, percentiles,
jobclass, method);
37% Normalize percentiles to [0, 1] range
38if any(percentiles > 1)
39 percentiles = percentiles / 100;
44% Percentiles are a solve by-product, require a prior solve; see _kb/06-solver-catalog.md for rationale
45if ~self.hasAvgResults()
49% Check if FJ_codes percentile results are available
50if isfield(self.result, 'Percentile') && ~isempty(self.result.Percentile)
51 % Use FJ_codes results (pre-computed)
52 percResults = self.result.Percentile;
55 % Fall back to CDF-based percentile extraction
59% Determine which classes to return
62 classes = 1:sn.nclasses;
67 classIdx = find(strcmp(sn.classnames,
jobclass));
69 line_error(mfilename, 'Job class "%s" not found in model.',
jobclass);
73 % Class index provided
78% Build PercRT struct array
82 % Use pre-computed FJ_codes results
83 for idx = 1:length(classes)
86 if r > length(percResults.
RT) || isempty(percResults.
RT{r})
87 line_warning(mfilename,
'No percentile results for class %d.', r);
91 % Extract percentile data
for this class
92 classPercResults = percResults.RT{r};
94 % Interpolate to get requested percentiles (
if different from stored)
95 storedPercentiles = classPercResults.percentiles; % In percentage
form from mainFJ
96 storedValues = classPercResults.RTp;
98 % Convert requested percentiles to percentage
form for interpolation
99 % (percentiles are already normalized to [0,1] on line 28)
100 requestedPercentiles = percentiles * 100;
102 % Interpolate to requested percentiles
103 interpValues = interp1(storedPercentiles, storedValues, requestedPercentiles,
'linear',
'extrap');
105 PercRT(idx).class = sn.classnames{r};
106 PercRT(idx).percentiles = percentiles; % Keep in fractional
form [0,1]
107 PercRT(idx).values = interpValues;
108 PercRT(idx).K = percResults.K;
109 PercRT(idx).method = percResults.method;
112 % Extract percentiles from CDF
114 RD = self.getCdfRespT();
116 line_error(mfilename,
'Unable to compute percentiles. getCdfRespT not available for this model.');
119 for idx = 1:length(classes)
122 % Find CDF data
for this class
123 % RD
is a cell array with format RD{station,
class} = [F, X]
124 % where F are CDF probabilities and X are time values
125 % Search through stations to find non-empty CDF data
127 for i = 1:size(RD, 1)
128 if r <= size(RD, 2) && ~isempty(RD{i, r})
135 % CDF format
is [F, X] where F = probabilities, X = times
136 probs = cdfData(:, 1);
137 times = cdfData(:, 2);
139 % Remove duplicate probability values
for interpolation
140 [probs_unique, idx_unique] = unique(probs,
'last');
141 times_unique = times(idx_unique);
143 % Interpolate to find times at requested percentiles
144 percValues = interp1(probs_unique, times_unique, percentiles,
'linear',
'extrap');
146 PercRT(idx).class = sn.classnames{r};
147 PercRT(idx).percentiles = percentiles; % Keep in fractional
form [0,1]
148 PercRT(idx).values = percValues;
149 PercRT(idx).method =
'cdf';
154% Build PercTable
for display
160 for idx = 1:length(PercRT)
161 nPercentiles = length(PercRT(idx).percentiles);
162 for p = 1:nPercentiles
163 JobClass{end+1,1} = PercRT(idx).class;
164 Percentile(end+1,1) = PercRT(idx).percentiles(p);
165 ResponseTime(end+1,1) = PercRT(idx).values(p);
169 JobClass = label(JobClass);
170 PercTable = Table(JobClass, Percentile, ResponseTime);