Skip to content

Instantly share code, notes, and snippets.

@ruslander
Created September 7, 2019 16:41
Show Gist options
  • Save ruslander/6c62423f4c11f3a93d244575dd0bd4a9 to your computer and use it in GitHub Desktop.
Save ruslander/6c62423f4c11f3a93d244575dd0bd4a9 to your computer and use it in GitHub Desktop.
multiple wrongs don't make it right
Parallel queues model with PDQ
Took as an example the "Internet Provider" from "The practical Performance Analyst".
#!/usr/bin/perl
use pdq;
# Globals
$arrivRate = 3;
$servTime = 2;
$engs = 10;
# Initialize PDQ and add a comment about the model
pdq::Init("Internet Service Provilder");
# Define the workload and circuit type
pdq::CreateOpen("Support", $arrivRate);
# Define the queueing center
#pdq::CreateNode("Server", $pdq::CEN, $pdq::FCFS);
pdq::CreateMultiNode($engs, "Eng", $pdq::MSO, $pdq::FCFS);
# Define service demand due to workload on the queueing center
pdq::SetDemand("Eng", "Support", $servTime);
# Change units labels to suit
pdq::SetWUnit("Cust");
pdq::SetTUnit("Min");
# Solve the model
# Must use the Canonical method for an open network
pdq::Solve($pdq::CANON);
# Generate a generic performance report
pdq::Report();
And I know it is wrong beacuse should give R=5min.
Changing $engs to 18 should change to R=3min. Glanced through
PDQ docs but cannot figure out what I'm doing wrong :)
If it is a quick answer then would appreciate your help. Otherwise
it is not worth ir :D
As always thank you very much!
@DrQz
Copy link

DrQz commented Sep 7, 2019

#!/usr/bin/perl
#
# Modified Ruslan code 
# Let's just try to reproduce first Table on p.60.
#
# Created by NJG on Saturday, September 07, 2019

use pdq;

$arrivRate = 3; # calls per minute
$servTime  = 2; # minutes per call
$engs = 10;     # thingies

pdq::Init("Internet Service Provider");

# Create the workload for ONE parallel queue
# since ALL others must be the same as that one.
# However, each center only sees 1/10th of the total arrival stream

pdq::CreateOpen("query", $arrivRate / $engs);

$name = "Eng";
pdq::CreateNode($name, $pdq::CEN, $pdq::FCFS);
pdq::SetDemand($name, "query", $servTime);

pdq::SetTUnit("Mins");
pdq::SetWUnit("Calls");

pdq::Solve($pdq::CANON);
pdq::Report();

@DrQz
Copy link

DrQz commented Sep 7, 2019

               ********   RESOURCE Performance   ********

Metric          Resource     Work              Value   Unit
------          --------     ----              -----   ----
Capacity        Eng          query                 1   Servers
Throughput      Eng          query            0.3000   Calls/Mins
In service      Eng          query            0.6000   Calls
Utilization     Eng          query           60.0000   Percent
Queue length    Eng          query            1.5000   Calls
Waiting line    Eng          query            0.9000   Calls
Waiting time    Eng          query            3.0000   Mins
Residence time  Eng          query            5.0000   Mins

@DrQz
Copy link

DrQz commented Sep 8, 2019

# parafast.r
#
# Gunther's theorem (1996): Parallel processing is just fast sequential processing.
#
# Show equivalence of: 
# 	1) k-parallel queues each with service time S
# 	2) k-tandem queues each with speed S/k
#
# Created by NJG on Wednesday, October 7, 2009
 
library(pdq)

workname  <- "AllWork"
arrivrate <- 0.5
servtime  <- 1.0
paraQMax  <- 2

paraname  <- 1:paraQMax

Init("Fast Serial Queues")
CreateOpen(workname, arrivrate)
CreateNode("FastQ", CEN, FCFS)
SetDemand("FastQ", workname, servtime/paraQMax)
Solve(CANON)

# Compare with analytic formula: Rk = (S/k) / (1 - (S/k))
cat(sprintf("Fast serial queues: %d\n", paraQMax))
rtimeFast <- (servtime/paraQMax) / (1 - (arrivrate * (servtime / paraQMax)))
cat(sprintf("FastQ Eqn: R = %6.4f\n", rtimeFast))
cat(sprintf("FastQ PDQ: R = %6.4f\n", GetResidenceTime("FastQ", workname, TRANS)))

cat("---\n")

Init("Parallel Queues")
CreateOpen(workname, arrivrate)

for (k in 1:paraQMax) {
	paraname[k] <- sprintf("ParaQ%d", k)
	CreateNode(paraname[k], CEN, FCFS)
	SetDemand(paraname[k], workname, servtime / paraQMax)
}

Solve(CANON)

# Compare with analytic formula: Rpara = S / (1 - (S/k))
rtimePara <- servtime/(1-((arrivrate/paraQMax)*servtime))
cat(sprintf("Parallel queues: %d\n", paraQMax))
cat(sprintf("ParaQ Eqn: R = %6.4f\n", rtimePara))
cat(sprintf("ParaQ PDQ: R = %6.4f (Residence Time)\n", 
            GetResidenceTime(paraname[1], workname, TRANS)))
cat(sprintf("ParaQ PDQ: R = %6.4f (Residence Time x %d)\n", 
            GetResidenceTime(paraname[1], workname, TRANS) * paraQMax, paraQMax))
cat(sprintf("ParaQ PDQ: R = %6.4f (Response Time sum)\n", 
            GetResponse(TRANS, workname)))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment