Skip to content

Commit 5a379e3

Browse files
committed
DOCS: Add case study for Project One
1 parent e8721ca commit 5a379e3

File tree

2 files changed

+143
-3
lines changed

2 files changed

+143
-3
lines changed

README.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,10 @@ The overall aim of this module is twofold:
2828
* [Usage and Examples](docs/en/examples.md)
2929
* [Performance impact/considerations](#performance-impactconsiderations)
3030
* [Queued jobs](#queued-jobs)
31-
* [Fluent support](#fluent-support)
32-
* [GridField Orderable support](#gridfield-orderable-support)
33-
* [License](#license)
31+
* [Case Studies](docs/en/case-studies.md)
32+
* [Fluent support](docs/en/fluent.md)
33+
* [GridField Orderable support](docs/en/gridfield-orderable.md)
34+
* [License](license.md)
3435
* [Maintainers](#maintainers)
3536
* [Development and contribution](#development-and-contribution)
3637

@@ -280,6 +281,10 @@ If you want to prevent content authors from getting slightly slower responses wh
280281
job to generate the cache updates by injecting over `CacheKeyExtension` and updating `triggerEvent` to create a job then
281282
call `CacheRelationService::singleton()->processChange($this->DataObject)` in the job.
282283

284+
## Case studies
285+
286+
See: [Case studies](docs/en/case-studies.md)
287+
283288
## Fluent support
284289

285290
See: [Fluent support](docs/en/fluent.md)

docs/en/case-studies.md

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
# Case Studies
2+
3+
* [Project One](#project-one)
4+
* [General site info](#general-site-info)
5+
* [Current state of caching](#current-state-of-caching)
6+
* [Goals](#goals)
7+
* [KFC implementation](#kfc-implementation)
8+
* [Results](#results)
9+
* [DB queries](#db-queries)
10+
* [Request times](#request-times)
11+
* [Conclusion](#conclusion)
12+
* [Project Two (TBA)](#project-two--tba-)
13+
14+
# Project One
15+
16+
## General site info
17+
18+
* The site contains roughly ~2,000 published pages.
19+
* Pages contain on average 4 (Elemental) blocks each.
20+
* Pages contain other "non-block" elements, like banners, menus, footer, etc.
21+
* There is a good mixture of block types (14), including multiple "complex" blocks where there is multiple levels of
22+
nested dependencies (EG: Carousel has Item relationships, Items have Image and Linkable relationships).
23+
* The primary navigation includes nesting to all levels of the SiteTree (which is why we're going to see a high
24+
numbers of DB queries on un-cached requests).
25+
* Optimising the Menu is not a concern of this case study, but we do hope to see some improvements from switching
26+
to KFC.
27+
28+
## Current state of caching
29+
30+
* Project One suffers from some of the pain points that KFC attempts to solve.
31+
* Some cache keys are a bit complicated and might be difficult for new devs to get up to speed with.
32+
* Models with high levels of nesting have cache keys that do not invalidate at all desired times.
33+
* EG: The "Carousel problem". A Carousel has Items, Items have Links and Images, and it's far too costly to
34+
calculate a cache key for a Carousel that includes the appropriate Images/Links/etc.
35+
* Some cache keys might invalidate too often.
36+
* EG: They might invalidate when a global event happens, like "invalidate all Menus when any Linkable model updates"
37+
(not only Links that are relevant to the Menu).
38+
* The site has a relatively high number of DB queries for every un-cached request (noted in "General site info").
39+
* The number of DB queries is currently a bottleneck for Project One.
40+
* The site already has a pretty balanced caching policy. That being, the cost of calculating a key is weighed against
41+
the value (EG: the "Carousel problem", where the solution for us was to not include Images/Links in the cache key).
42+
* I do not believe the cost of calculating any single cache key for the site is unreasonable.
43+
44+
## Goals
45+
46+
* Improve management of cache keys for developers.
47+
* Improve the specificity of our cache keys (EG: solving the "Carousel problem").
48+
* Given that the site already has relatively performant cache keys, we're not expecting any huge performance
49+
improvements, but...
50+
* We would like to see some reduction in the number of DB queries, and
51+
* Ideally we want no negative impact to load times.
52+
53+
## KFC implementation
54+
55+
Implementation of KFC to the project included:
56+
57+
* Reviewing any/all methods found in Page models and controllers related to providing cache keys.
58+
* Replacing the use of these methods with `cares` and/or `global_cares` considerations on the appropriate page
59+
classes and relationships.
60+
* Adding a "global" key to `SiteConfig` that contains a `global_cares` for `SiteTree`. This is discussed a bit in
61+
[Headers, Footers, and other "global" content areas](examples.md#headers-footers-and-other--global--content-areas).
62+
* Reviewing any/all methods found in (Elemental) blocks related to providing cache keys.
63+
* Replacing the use of these methods with `cares` on appropriate block relationships.
64+
65+
Implementaiton took (roughly) 40 minutes.
66+
67+
## Results
68+
69+
These are not the most comprehensive tests, but we believe they show enough.
70+
71+
### DB queries
72+
73+
Installed [Lekoala/Debugbar](https://github.com/lekoala/silverstripe-debugbar) so that we can see the number of DB
74+
queries we are making on each page request.
75+
76+
* "1st" requests were made as a separate request after a `?flush=1`, so there is no active partial cache. Generating the
77+
cache would also be part of this request.
78+
* "2nd" requests were a fast follow request where a partial cache is now available.
79+
80+
**Original implementation:**
81+
82+
* 1st: 1,430 queries
83+
* 2nd: 96 queries
84+
85+
**KFC implementation:**
86+
87+
* 1st: 1,219 queries
88+
* 2nd: 73 queries
89+
90+
**Outcome:** Some positive improvements to DB queries for both the fresh request and the request with partial caches
91+
available.
92+
93+
### Request times
94+
95+
This test was performed by running a basic Siege test:
96+
97+
```bash
98+
siege -d1 -r200 -c4 --no-parser http://project-one.local/
99+
```
100+
101+
**Original implementation:**
102+
103+
```
104+
Elapsed time: 163.82 secs
105+
Response time: 0.28 secs
106+
Transaction rate: 4.88 trans/sec
107+
Throughput: 0.61 MB/sec
108+
Concurrency: 1.35
109+
Longest transaction: 5.30
110+
Shortest transaction: 0.18
111+
```
112+
113+
**KFC implementation:**
114+
115+
```
116+
Elapsed time: 162.95 secs
117+
Response time: 0.26 secs
118+
Transaction rate: 4.91 trans/sec
119+
Throughput: 0.61 MB/sec
120+
Concurrency: 1.30
121+
Longest transaction: 4.98
122+
Shortest transaction: 0.17
123+
```
124+
125+
**Outcome:** I would say that the difference here is negligable, but there is a slight improvement when using KFC.
126+
Overall, I think this meets expectations, given that we knew that Project One already had performant cached keys.
127+
128+
### Conclusion
129+
130+
Overall, considering ~40 minutes of effort to upgrade the project to using KFC, I would say that the outcomes for both
131+
DB queries and request times are pretty great.
132+
133+
# Project Two (TBA)
134+
135+
TBA

0 commit comments

Comments
 (0)