LINE Solver
MATLAB API documentation
Loading...
Searching...
No Matches
gallery_multitier_storage.m
1% Layered Queueing Network (LQN) - Production 4-Tier J2EE Architecture with Cache
2%
3% This example extends the 4-tier J2EE model (example_layered_production_4tier.m)
4% with a dedicated CACHE LAYER (Layer 4), demonstrating:
5%
6% Layer 1: CLIENT LAYER
7% - Reference task with 1 user (closed class)
8% - Represents browser clients with sequential user operations
9%
10% Layer 2: APPLICATION LAYER
11% - Service task handling web requests
12% - Multiple entries for different operations
13% - Complex activity precedence with branching
14%
15% Layer 3: DATABASE LAYER
16% - Primary data storage
17% - Cache lookup operations (via calls to cache layer)
18% - Write and log operations
19%
20% Layer 4: CACHE LAYER (NEW)
21% - Dedicated cache with LRU replacement strategy
22% - Cache capacity: 2 items out of 10 total items
23% - Uniform access distribution
24% - Cache hit/miss modeling with different service times
25%
26% Model demonstrates:
27% - Cache hit/miss precedence patterns (CacheAccess)
28% - ItemEntry for cache-aware workloads
29% - CacheTask with replacement strategy
30% - Integration of caching into multi-layer system
31%
32% KNOWN LIMITATION:
33% SolverLN has issues with routing synchronous cache calls in complex multi-layer
34% networks with precedence constraints. This model will fail during layer decomposition.
35% For cache support in production systems, use:
36% - Simpler 2-3 layer models (example_layeredcache_async.m)
37% - Or implement caching at application layer (no cross-layer cache calls)
38%
39% Compare with: example_layered_production_4tier.m (non-cached variant - WORKS)
40
41clear all;
42
43%% Create the model
44model = LayeredNetwork('testLQN3_Cache');
45
46%% Layer 1: CLIENT LAYER
47P0 = Processor(model, 'P0', 1, SchedStrategy.PS);
48T0 = Task(model, 'T0', 1, SchedStrategy.REF).on(P0); % Reference task with 1 user
49E0 = Entry(model, 'E0').on(T0); % Single entry point
50
51%% Layer 2: APPLICATION SERVER LAYER
52P1 = Processor(model, 'P1', 1, SchedStrategy.PS);
53T1 = Task(model, 'T1', 1, SchedStrategy.FCFS).on(P1);
54E10 = Entry(model, 'E10').on(T1); % renderHomePage
55E11 = Entry(model, 'E11').on(T1); % processProductPage
56E12 = Entry(model, 'E12').on(T1); % handleLogin
57E13 = Entry(model, 'E13').on(T1); % checkoutWorkflow
58
59%% Layer 3: DATABASE LAYER
60P2 = Processor(model, 'P2', 1, SchedStrategy.PS);
61T2 = Task(model, 'T2', 1, SchedStrategy.FCFS).on(P2);
62E20 = Entry(model, 'E20').on(T2); % readUserProfile
63E21 = Entry(model, 'E21').on(T2); % getProductInfo
64E22 = Entry(model, 'E22').on(T2); % writeOrderData
65E23 = Entry(model, 'E23').on(T2); % logSessionEvent
66
67%% Layer 4: CACHE LAYER (NEW)
68% Cache configuration: 10 items total, capacity of 2, LRU replacement
69totalitems = 10;
70cachecapacity = 2;
71pAccess = DiscreteSampler((1/totalitems)*ones(1, totalitems)); % Uniform access
72P3 = Processor(model, 'P3', 1, SchedStrategy.PS);
73T3 = CacheTask(model, 'T3', totalitems, cachecapacity, ReplacementStrategy.LRU, 1).on(P3);
74E3 = ItemEntry(model, 'E3', totalitems, pAccess).on(T3); % accessCache
75
76%% CLIENT LAYER ACTIVITIES
77% Sequential processing flow: login → browse → shop → checkout
78A0 = Activity(model, 'A0', Exp(1.0)).on(T0).boundTo(E0).synchCall(E12, 1.0); % login -> handleLogin
79A1 = Activity(model, 'A1', Exp(1.0)).on(T0).synchCall(E10, 1.0); % browseSession -> renderHomePage
80A2 = Activity(model, 'A2', Exp(1.0)).on(T0).synchCall(E11, 1.0); % viewProductPage -> processProductPage
81A3 = Activity(model, 'A3', Exp(1.0)).on(T0).synchCall(E13, 1.0); % submitCheckout -> checkoutWorkflow
82
83%% APPLICATION LAYER ACTIVITIES
84% Entry E10: renderHomePage
85B0 = Activity(model, 'B0', Exp(1.0)).on(T1).boundTo(E10); % renderStaticContent
86B1 = Activity(model, 'B1', Exp(1.0)).on(T1).repliesTo(E10); % fetchRecommendations
87
88% Entry E11: processProductPage
89B2 = Activity(model, 'B2', Exp(1.0)).on(T1).boundTo(E11); % parseRequest
90B3 = Activity(model, 'B3', Exp(1.0)).on(T1).synchCall(E21, 1.0).repliesTo(E11); % getProductDetails -> getProductInfo
91
92% Entry E12: handleLogin
93B4 = Activity(model, 'B4', Exp(1.0)).on(T1).boundTo(E12).synchCall(E20, 1.0).repliesTo(E12); % validateCredentials -> readUserProfile
94
95% Entry E13: checkoutWorkflow
96B5 = Activity(model, 'B5', Exp(1.0)).on(T1).boundTo(E13); % verifyCart
97B6 = Activity(model, 'B6', Exp(1.0)).on(T1); % computeTotalPrice
98B7 = Activity(model, 'B7', Exp(1.0)).on(T1).synchCall(E22, 1.0); % WriteOrder (no reply - or-fork will reply)
99B7a = Activity(model, 'B7a', Exp(1.0)).on(T1).repliesTo(E13); % skipLog (70% probability)
100B7b = Activity(model, 'B7b', Exp(1.0)).on(T1).synchCall(E23, 1.0).repliesTo(E13); % logOrder (30% probability)
101
102%% DATABASE LAYER ACTIVITIES
103% Entry E20: readUserProfile
104C0 = Activity(model, 'C0', Exp(1.0)).on(T2).boundTo(E20); % parseReadQuery
105C1 = Activity(model, 'C1', Exp(1.0)).on(T2).synchCall(E3, 1.0).repliesTo(E20); % fetchFromDisk -> accessCache
106
107% Entry E21: getProductInfo (cache-aware)
108C2 = Activity(model, 'C2', Exp(1.0)).on(T2).boundTo(E21).synchCall(E3, 1.0).repliesTo(E21); % readCache -> accessCache
109
110% Entry E22: writeOrderData
111C3 = Activity(model, 'C3', Exp(1.0)).on(T2).boundTo(E22); % parseWriteQuery
112C4 = Activity(model, 'C4', Exp(1.0)).on(T2); % writeToDisk
113C5 = Activity(model, 'C5', Exp(1.0)).on(T2).repliesTo(E22); % updateIndex
114
115% Entry E23: logSessionEvent
116C6 = Activity(model, 'C6', Exp(1.0)).on(T2).boundTo(E23).repliesTo(E23); % appendToLog
117
118%% CACHE LAYER ACTIVITIES
119% Immediate arrival processing
120D0 = Activity(model, 'D0', Immediate()).on(T3).boundTo(E3); % arrival
121D1a = Activity(model, 'D1a', Exp(1.0)).on(T3).repliesTo(E3); % cache hit (fast)
122D1b = Activity(model, 'D1b', Exp(0.5)).on(T3).repliesTo(E3); % cache miss (slow)
123
124%% ACTIVITY PRECEDENCES - CLIENT LAYER
125% Sequential flow through all client operations
126T0.addPrecedence(ActivityPrecedence.Serial(A0, A1, A2, A3));
127
128%% ACTIVITY PRECEDENCES - APPLICATION LAYER
129% Path 1: renderHomePage flow
130T1.addPrecedence(ActivityPrecedence.Serial(B0, B1));
131
132% Path 2: processProductPage flow
133T1.addPrecedence(ActivityPrecedence.Serial(B2, B3));
134
135% Path 3: checkoutWorkflow flow with branching
136T1.addPrecedence(ActivityPrecedence.Serial(B5, B6, B7)); % Sequential: verify -> compute -> write
137T1.addPrecedence(ActivityPrecedence.OrFork(B7, {B7a, B7b}, [0.7, 0.3])); % 70% skip logging, 30% log
138% Note: Both B7a and B7b reply to E13, providing implicit join
139
140%% ACTIVITY PRECEDENCES - DATABASE LAYER
141% Query path 1: readUserProfile
142T2.addPrecedence(ActivityPrecedence.Serial(C0, C1));
143
144% Query path 2: writeOrderData with index update
145T2.addPrecedence(ActivityPrecedence.Serial(C3, C4, C5));
146
147%% ACTIVITY PRECEDENCES - CACHE LAYER
148% Cache access precedence: arrival determines hit/miss
149T3.addPrecedence(ActivityPrecedence.CacheAccess(D0, {D1a, D1b}));
150
151%% SOLVE WITH SOLVERMVA (Layer solver) inside SolverLN
152fprintf('\n=== Solving 4-Tier LQN with Cache using SolverLN + MVA ===\n');
153lnoptions = LN.defaultOptions;
154lnoptions.verbose = VerboseLevel.STD;
155mvaopt = MVA.defaultOptions;
156mvaopt.verbose = VerboseLevel.SILENT;
157
158solver = LN(model, @(layer) MVA(layer, mvaopt), lnoptions);
159AvgTable = solver.getAvgTable;
160
161fprintf('\n=== Results ===\n');
162disp(AvgTable);
163
164%% Display cache statistics if available
165fprintf('\n=== Cache Performance (if available) ===\n');
166if isprop(solver, 'cache_stats')
167 disp(solver.cache_stats);
168else
169 fprintf('Cache statistics not available from this solver.\n');
170end
171
172%% Comparison notes
173fprintf('\n=== Comparison with Non-Cached Variant ===\n');
174fprintf('Expected impacts of cache layer:\n');
175fprintf('- Lower product info query response times (cache hits)\n');
176fprintf('- Higher overall throughput (cached lookups are fast)\n');
177fprintf('- Cache replacement activity (LRU eviction)\n');
178fprintf('See: example_layered_production_4tier.m for non-cached baseline\n');