Result:
root@debian:/home/penguin# ab -r -k -c 20 -n 250 https://blog.astropenguin.net/
This is ApacheBench, Version 2.3 <$Revision: 1604373 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking blog.astropenguin.net (be patient)
Completed 100 requests
Completed 200 requests
Finished 250 requests
Server Software: Apache/2.4.10
Server Hostname: blog.astropenguin.net
Server Port: 443
SSL/TLS Protocol: TLSv1.2,ECDHE-RSA-AES256-GCM-SHA384,2048,256
Document Path: /
Document Length: 17570 bytes
Concurrency Level: 20
Time taken for tests: 53.077 seconds
Complete requests: 250
Failed requests: 0
Keep-Alive requests: 250
Total transferred: 4460520 bytes
HTML transferred: 4392500 bytes
Requests per second: 4.71 [#/sec] (mean)
Time per request: 4246.175 [ms] (mean)
Time per request: 212.309 [ms] (mean, across all concurrent requests)
Transfer rate: 82.07 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 118 551.2 0 3493
Processing: 969 4099 1099.0 3958 6260
Waiting: 954 4084 1098.8 3942 6245
Total: 969 4218 1250.7 4136 8561
Percentage of the requests served within a certain time (ms)
50% 4136
66% 4975
75% 5060
80% 5244
90% 5519
95% 5899
98% 7678
99% 8472
100% 8561 (longest request)
The result has proven that my site is shit.
BotanJS API Blockage
The problem causing the request to wait was mainly because Rosemary was waiting for the Service API to return the corresponding js/css.
Js/CSS are mostly considered static, as long as the source haven't changed. It should be delivered quickly without any problem.
However, because of the nature of BotanJs. it compiles these resources on the fly and the API call is done via http internally ( http://localhost:5000/ ). Shit, I've just created a problem that shouldn't be a problem!
Welp, I guess I need a way to cache the resources acquisition mappings. They probably wouldn't change if the content stays the same. ( That depends on what components I need for writing each blog entry. As the BotanJs is going to minimize the size of the compiled source to extreme, 90%1 of the style / script will be call / used on that page. )
An Organic Approach
After some struggling, I have listed some possible approach I could think of:
1. Compile everything into one single, big, all-purpose js/css file. Serve them on every page ( General approach )
2. Compile the scripts in Rosemary, eliminating the *calling layer*
3. Use a cached map to lookup the corresponding file
Most of the site goes for Solution 1 because it is easier to manage and reliable. And because of that js/css is already in their computer after the first load. The next page they visit will be rendering faster because the only resource the browser need to get is the page itself.
I'd say FUCK THAT. Most people stumble upon my blog are just one-time visitor. So every single page should be optimized and should be equally fast even for first load. I hate jquery because many people are using then like whatever and punch in those empty calls2. Using this approach just violates the policy of BotanJs. The goal of BotanJs is to eliminate ( or minimize, at least ) those useless crap when it is not needed.
The only way Rosemary can tell if the resource is up to date is by asking the Service API. But asking it every time does no good. So to reduce the overhead. I have to ask in a way that it will not make the request to wait.
Solution 2 is not practical because the compiling / resolving process costs time and probably won't do much comparing to the http overhead. But it could be done via Node.js.
So I go for Solution 3. By setting a timeout for the Service calling, it will instead look for the file compiled last time and use it after the timeout occurred.
Deployment issue
To ensure the content delivery is always the latest. I have to make sure the old content should not be delivered after the source has been updated. This could be achieved by clearing the cached mappings after deployment.
That's why I call this organic - when the number of client increases, the server become *rash* and try to deliver contents as fast as possible. So it ain't have time to wait for that Service call to return.
This was essentially the same concept I used in implementing the lastlog - with the cooldown approach.
( A day later )
Now, let's see the results:
root@debian:/home/penguin# ab -r -k -c 20 -n 250 https://blog.astropenguin.net/
This is ApacheBench, Version 2.3 <$Revision: 1604373 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/
Benchmarking blog.astropenguin.net (be patient)
Completed 100 requests
Completed 200 requests
Finished 250 requests
Server Software: Apache/2.4.10
Server Hostname: blog.astropenguin.net
Server Port: 443
SSL/TLS Protocol: TLSv1.2,ECDHE-RSA-AES256-GCM-SHA384,2048,256
Document Path: /
Document Length: 17570 bytes
Concurrency Level: 20
Time taken for tests: 49.450 seconds
Complete requests: 250
Failed requests: 0
Keep-Alive requests: 250
Total transferred: 4460520 bytes
HTML transferred: 4392500 bytes
Requests per second: 5.06 [#/sec] (mean)
Time per request: 3956.035 [ms] (mean)
Time per request: 197.802 [ms] (mean, across all concurrent requests)
Transfer rate: 88.09 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 109 550.3 0 3743
Processing: 452 3758 838.6 3928 6214
Waiting: 437 3742 838.6 3911 6199
Total: 452 3866 984.6 3932 8504
Percentage of the requests served within a certain time (ms)
50% 3932
66% 3973
75% 4254
80% 4275
90% 4341
95% 5416
98% 7075
99% 7116
100% 8504 (longest request)
Aaaaand it is still shit. But from the log I could see that the overhead of API calling is solved.
Next stop, profiling! 斟酌 鵬兄
Thu Jun 02 2016 03:17:52 GMT+0000 (Coordinated Universal Time)
Last modified: Sun Apr 10 2022 12:30:38 GMT+0000 (Coordinated Universal Time)