Skip to content

Commit 11ee1af

Browse files
committed
Transfer final state from Task 4
1 parent 08eeca0 commit 11ee1af

26 files changed

+3494
-20
lines changed

.eslintrc.yml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
env:
2+
browser: true
3+
node: true
4+
es6: true
5+
extends: 'eslint:recommended'
6+
globals:
7+
Atomics: readonly
8+
SharedArrayBuffer: readonly
9+
parserOptions:
10+
ecmaFeatures:
11+
jsx: true
12+
ecmaVersion: 2018
13+
sourceType: module
14+
plugins:
15+
- react
16+
rules: {}

.ruby-version

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
2.6.3
1+
2.7.7

Gemfile

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# rubocop:disable LineLength
22
source "https://rubygems.org"
3-
ruby "2.6.3"
3+
ruby "2.7.7"
44

55
# Enforce git to transmitted via https.
66
# workaround until bundler 2.0 is released.
@@ -59,19 +59,22 @@ gem "jquery-rails", "~> 4.3"
5959
gem "kaminari", "~> 1.1"
6060
gem "libhoney", "~> 1.11"
6161
gem "liquid", "~> 4.0"
62+
gem 'newrelic_rpm', "~> 9.6"
6263
gem "nokogiri", "~> 1.10"
6364
gem "octokit", "~> 4.13"
6465
gem "omniauth", "~> 1.9"
6566
gem "omniauth-github", "~> 1.3"
6667
gem "omniauth-twitter", "~> 1.4"
6768
gem "pg", "~> 1.1"
69+
gem "prometheus_exporter", "~> 2.0"
6870
gem "pry", "~> 0.12"
6971
gem "pry-rails", "~> 0.3"
7072
gem "puma", "~> 3.12"
7173
gem "pundit", "~> 2.0"
7274
gem "pusher", "~> 1.3"
7375
gem "pusher-push-notifications", "~> 1.0"
7476
gem "rack-host-redirect", "~> 1.3"
77+
gem "rack-mini-profiler", "~> 3.1", require: false
7578
gem "rack-timeout", "~> 0.5"
7679
gem "rails", "~> 5.1.6"
7780
gem "rails-assets-airbrake-js-client", "~> 1.5", source: "https://rails-assets.org"
@@ -89,7 +92,7 @@ gem "sdoc", "~> 1.0", group: :doc
8992
gem "serviceworker-rails", "~> 0.5"
9093
gem "share_meow_client", "~> 0.1"
9194
gem "sitemap_generator", "~> 6.0"
92-
gem "skylight", "~> 3.1"
95+
gem "skylight", "~> 4.3"
9396
gem "slack-notifier", "~> 2.3"
9497
gem "sprockets", "~> 3.7"
9598
gem "staccato", "~> 0.5"
@@ -103,6 +106,10 @@ gem "validate_url", "~> 1.0"
103106
gem "webpacker", "~> 3.5"
104107
gem "webpush", "~> 0.3"
105108

109+
group :localproduction, :development do
110+
gem 'meta_request', "~> 0.7"
111+
end
112+
106113
group :development do
107114
gem "better_errors", "~> 2.5"
108115
gem "binding_of_caller", "~> 0.8"

Gemfile.lock

Lines changed: 28 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,7 @@ GEM
137137
descendants_tracker (~> 0.0.4)
138138
ice_nine (~> 0.11.0)
139139
thread_safe (~> 0.3, >= 0.3.1)
140+
base64 (0.2.0)
140141
bcrypt (3.1.12)
141142
benchmark-ips (2.7.2)
142143
better_errors (2.5.0)
@@ -212,7 +213,7 @@ GEM
212213
coffee-script-source
213214
execjs
214215
coffee-script-source (1.12.2)
215-
concurrent-ruby (1.1.5)
216+
concurrent-ruby (1.2.2)
216217
connection_pool (2.2.2)
217218
counter_culture (2.1.2)
218219
activerecord (>= 3.0.0)
@@ -317,7 +318,7 @@ GEM
317318
faraday_middleware (>= 0.9)
318319
loofah (>= 2.0)
319320
sax-machine (>= 1.0)
320-
ffi (1.9.25)
321+
ffi (1.16.3)
321322
figaro (1.1.1)
322323
thor (~> 0.14)
323324
fission (0.5.0)
@@ -536,7 +537,7 @@ GEM
536537
mime-types (~> 3.0)
537538
multi_xml (>= 0.5.2)
538539
httpclient (2.8.3)
539-
i18n (1.6.0)
540+
i18n (1.14.1)
540541
concurrent-ruby (~> 1.0)
541542
ice_nine (0.11.2)
542543
inflecto (0.0.2)
@@ -592,13 +593,16 @@ GEM
592593
memoizable (0.4.2)
593594
thread_safe (~> 0.3, >= 0.3.1)
594595
memory_profiler (0.9.12)
596+
meta_request (0.7.4)
597+
rack-contrib (>= 1.1, < 3)
598+
railties (>= 3.0.0, < 7.1)
595599
method_source (0.9.2)
596600
mime-types (3.2.2)
597601
mime-types-data (~> 3.2015)
598602
mime-types-data (3.2018.0812)
599603
mini_mime (1.0.1)
600604
mini_portile2 (2.4.0)
601-
minitest (5.11.3)
605+
minitest (5.20.0)
602606
momentjs-rails (2.20.1)
603607
railties (>= 3.1)
604608
msgpack (1.2.4)
@@ -612,8 +616,10 @@ GEM
612616
net-http-persistent (3.0.0)
613617
connection_pool (~> 2.2)
614618
netrc (0.11.0)
619+
newrelic_rpm (9.6.0)
620+
base64
615621
nio4r (2.3.1)
616-
nokogiri (1.10.1)
622+
nokogiri (1.10.2)
617623
mini_portile2 (~> 2.4.0)
618624
notiffany (0.1.1)
619625
nenv (~> 0.1)
@@ -651,6 +657,8 @@ GEM
651657
ast (~> 2.4.0)
652658
pg (1.1.4)
653659
powerpack (0.1.2)
660+
prometheus_exporter (2.0.8)
661+
webrick
654662
pry (0.12.2)
655663
coderay (~> 1.1.0)
656664
method_source (~> 0.9.0)
@@ -675,8 +683,12 @@ GEM
675683
pusher-signature (0.1.8)
676684
raabro (1.1.6)
677685
rack (2.0.6)
686+
rack-contrib (2.4.0)
687+
rack (< 4)
678688
rack-host-redirect (1.3.0)
679689
rack
690+
rack-mini-profiler (3.1.1)
691+
rack (>= 1.2.0)
680692
rack-protection (2.0.4)
681693
rack
682694
rack-proxy (0.6.5)
@@ -843,9 +855,9 @@ GEM
843855
tilt (~> 2.0)
844856
sitemap_generator (6.0.2)
845857
builder (~> 3.0)
846-
skylight (3.1.4)
847-
skylight-core (= 3.1.4)
848-
skylight-core (3.1.4)
858+
skylight (4.3.2)
859+
skylight-core (= 4.3.2)
860+
skylight-core (4.3.2)
849861
activesupport (>= 4.2.0)
850862
slack-notifier (2.3.2)
851863
smart_properties (1.13.1)
@@ -895,7 +907,7 @@ GEM
895907
multipart-post (~> 2.0)
896908
naught (~> 1.0)
897909
simple_oauth (~> 0.3.0)
898-
tzinfo (1.2.5)
910+
tzinfo (1.2.11)
899911
thread_safe (~> 0.1)
900912
uber (0.1.0)
901913
uglifier (4.1.20)
@@ -932,6 +944,7 @@ GEM
932944
webpush (0.3.2)
933945
hkdf (~> 0.2)
934946
jwt
947+
webrick (1.8.1)
935948
websocket-driver (0.6.5)
936949
websocket-extensions (>= 0.1.0)
937950
websocket-extensions (0.1.3)
@@ -1012,14 +1025,17 @@ DEPENDENCIES
10121025
libhoney (~> 1.11)
10131026
liquid (~> 4.0)
10141027
memory_profiler (~> 0.9)
1028+
meta_request (~> 0.7)
10151029
nakayoshi_fork
1030+
newrelic_rpm (~> 9.6)
10161031
nokogiri (~> 1.10)
10171032
octokit (~> 4.13)
10181033
omniauth (~> 1.9)
10191034
omniauth-github (~> 1.3)
10201035
omniauth-twitter (~> 1.4)
10211036
parallel_tests (~> 2.27)
10221037
pg (~> 1.1)
1038+
prometheus_exporter (~> 2.0)
10231039
pry (~> 0.12)
10241040
pry-byebug (~> 3.7)
10251041
pry-rails (~> 0.3)
@@ -1029,6 +1045,7 @@ DEPENDENCIES
10291045
pusher (~> 1.3)
10301046
pusher-push-notifications (~> 1.0)
10311047
rack-host-redirect (~> 1.3)
1048+
rack-mini-profiler (~> 3.1)
10321049
rack-timeout (~> 0.5)
10331050
rails (~> 5.1.6)
10341051
rails-assets-airbrake-js-client (~> 1.5)!
@@ -1057,7 +1074,7 @@ DEPENDENCIES
10571074
simplecov (~> 0.16)
10581075
sinatra (~> 2.0)
10591076
sitemap_generator (~> 6.0)
1060-
skylight (~> 3.1)
1077+
skylight (~> 4.3)
10611078
slack-notifier (~> 2.3)
10621079
spring (~> 2.0)
10631080
spring-commands-rspec (~> 1.0)
@@ -1082,7 +1099,7 @@ DEPENDENCIES
10821099
zonebie (~> 0.6.1)
10831100

10841101
RUBY VERSION
1085-
ruby 2.6.3p62
1102+
ruby 2.7.7p221
10861103

10871104
BUNDLED WITH
10881105
1.17.3

Procfile.dev

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
web: bin/rails s -p 3000
22
webpacker: ./bin/webpack-dev-server
33
job: bin/rake jobs:work
4+
prometheus_exporter: bundle exec prometheus_exporter

Procfile.localproduction

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
web: bin/rails s -p 3000
2+
webpacker: ./bin/webpack-dev-server
3+
job: bin/rake jobs:work
4+
prometheus_exporter: bundle exec prometheus_exporter

app/views/stories/_main_stories_feed.html.erb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,9 @@
5555
<% if !user_signed_in? && i == 4 %>
5656
<%= render "stories/sign_in_invitation" %>
5757
<% end %>
58-
<%= render "articles/single_story", story: story %>
58+
<% cache story do %>
59+
<%= render "articles/single_story", story: story %>
60+
<% end %>
5961
<% end %>
6062
<% end %>
6163
<% if @stories.size > 1 %>

bin/startup

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,10 @@ end
1212

1313
chdir APP_ROOT do
1414
puts "== STARTING UP =="
15-
system! "foreman start -f Procfile.dev"
15+
if ENV['RAILS_ENV'] == 'localproduction'
16+
system! "bundle exec rake assets:precompile"
17+
system! "foreman start -f Procfile.localproduction"
18+
else
19+
system! "foreman start -f Procfile.dev"
20+
end
1621
end

bin/webpack-dev-server

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@ CONFIG_FILE = File.join(APP_PATH, "config/webpacker.yml")
1616
NODE_MODULES_PATH = File.join(APP_PATH, "node_modules")
1717
WEBPACK_CONFIG = File.join(APP_PATH, "config/webpack/#{NODE_ENV}.js")
1818

19-
DEFAULT_LISTEN_HOST_ADDR = NODE_ENV == "development" ? "localhost" : "0.0.0.0"
19+
LOCALHOST = NODE_ENV == "development" || NODE_ENV == "localproduction"
20+
DEFAULT_LISTEN_HOST_ADDR = LOCALHOST ? "localhost" : "0.0.0.0"
2021

2122
def args(key)
2223
index = ARGV.index(key)

case-study.md

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
# Case-study оптимизации
2+
3+
## Актуальная проблема
4+
5+
Нужно оптимизировать механизм загрузки главной страницы проекта `StoriesController#index`.
6+
7+
Я решил исправить эту проблему, оптимизировав рендеринг шаблонов.
8+
9+
## Формирование метрики
10+
11+
Для того, чтобы понимать, дают ли мои изменения положительный эффект на быстродействие программы я придумал использовать такую метрику: число секунд, требуемые для прохождения нагрузочного бенчмарка `ab` с 30 запросами к главной странице проекта.
12+
13+
## Вникаем в детали системы, чтобы найти главные точки роста
14+
15+
Для того, чтобы найти "точки роста" для оптимизации я воспользовался инструментами rack-mini-profiler, Prometheus, Grafana.
16+
17+
Вот какие проблемы удалось найти и решить
18+
19+
### Ваша находка №1
20+
21+
- какой отчёт показал главную точку роста
22+
23+
- rack-mini-profiler: заметное время занимает рендеринг `partial`-ов `_single_story.html.erb`, делаются 11 вызовов. Rendering: stories/\_main_stories_feed.html.erb duration 3.3ms, with children 57.1ms
24+
- ```
25+
Document Path: /
26+
Document Length: 139178 bytes
27+
28+
Concurrency Level: 1
29+
Time taken for tests: 2.373 seconds
30+
Complete requests: 30
31+
Failed requests: 0
32+
Total transferred: 4206630 bytes
33+
HTML transferred: 4175340 bytes
34+
Requests per second: 12.64 [#/sec] (mean)
35+
Time per request: 79.097 [ms] (mean)
36+
Time per request: 79.097 [ms] (mean, across all concurrent requests)
37+
Transfer rate: 1731.23 [Kbytes/sec] received
38+
39+
Connection Times (ms)
40+
min mean[+/-sd] median max
41+
Connect: 0 0 0.2 0 1
42+
Processing: 69 79 18.0 74 164
43+
Waiting: 69 79 18.0 74 164
44+
Total: 69 79 18.2 75 166
45+
46+
Percentage of the requests served within a certain time (ms)
47+
50% 75
48+
66% 77
49+
75% 79
50+
80% 80
51+
90% 89
52+
95% 111
53+
98% 166
54+
99% 166
55+
100% 166 (longest request)
56+
```
57+
58+
Нашей точкой роста будет число вызовов отдельных шаблонов `articles/_single_story.html.erb`
59+
60+
- как вы решили её оптимизировать
61+
- Применил кэширование в шаблоне при работе с коллекциями stories. Гипотеза состоит в том, что в случае не частых обновлений постов на главной странице кэширование снизит время изначальной загрузки за счет переиспользования данных об уже имеющихся постах.
62+
- как изменилась метрика
63+
64+
- Метрика снизилась с 2.37 сек до 1.42 сек
65+
66+
```
67+
Document Path: /
68+
Document Length: Variable
69+
70+
Concurrency Level: 1
71+
Time taken for tests: 1.423 seconds
72+
Complete requests: 30
73+
Failed requests: 0
74+
Total transferred: 4208029 bytes
75+
HTML transferred: 4176759 bytes
76+
Requests per second: 21.08 [#/sec] (mean)
77+
Time per request: 47.445 [ms] (mean)
78+
Time per request: 47.445 [ms] (mean, across all concurrent requests)
79+
Transfer rate: 2887.15 [Kbytes/sec] received
80+
81+
Connection Times (ms)
82+
min mean[+/-sd] median max
83+
Connect: 0 0 0.2 0 1
84+
Processing: 39 47 15.7 44 120
85+
Waiting: 39 47 15.7 43 119
86+
Total: 39 47 15.9 44 121
87+
88+
Percentage of the requests served within a certain time (ms)
89+
50% 44
90+
66% 45
91+
75% 45
92+
80% 47
93+
90% 49
94+
95% 84
95+
98% 121
96+
99% 121
97+
100% 121 (longest request)
98+
```
99+
100+
- как изменился отчёт профилировщика
101+
- Rendering: stories/\_main_stories_feed.html.erb duration 10.1ms, with children 10.2ms
102+
103+
## Результаты
104+
105+
В результате проделанной оптимизации удалось ускорить время рендеринга главной страницы более чем в полтора раза.

0 commit comments

Comments
 (0)