Skip to content

Commit 9beb33f

Browse files
committed
Make overview page display 1 benchmark data per week
1 parent 437e7ba commit 9beb33f

File tree

3 files changed

+181
-20
lines changed

3 files changed

+181
-20
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,4 @@ vendor/bundle
2424

2525
*.swp
2626
*.swo
27+
.ruby-version

app/models/repo.rb

Lines changed: 74 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -17,23 +17,80 @@ def generate_sparkline_data
1717

1818
charts = {}
1919

20-
self.benchmark_types.map do |benchmark_type|
21-
benchmark_type.benchmark_result_types.each do |benchmark_result_type|
22-
benchmark_runs = BenchmarkRun.select(:initiator_id, :result, :initiator_type).fetch_commit_benchmark_runs(
23-
benchmark_type.category,
24-
benchmark_result_type,
25-
2000
26-
)
27-
28-
runs = benchmark_runs.sort_by { |run| run.initiator.created_at }
29-
chart_builder = ChartBuilder.new(runs, benchmark_result_type).build_columns
30-
31-
charts[benchmark_type.category] ||= []
32-
charts[benchmark_type.category] << {
33-
benchmark_result_type: benchmark_result_type.name,
34-
columns: chart_builder.columns
35-
}
36-
end
20+
query = <<~SQL
21+
WITH min_max_dates AS (
22+
SELECT MIN(date_trunc('week', created_at)) AS start_week,
23+
MAX(date_trunc('week', created_at)) AS end_week
24+
FROM (
25+
SELECT created_at
26+
FROM commits
27+
WHERE repo_id = #{self.id}
28+
) AS subq
29+
),
30+
weeks AS (
31+
SELECT generate_series(start_week, end_week, '7 days') AS weekstart
32+
FROM min_max_dates
33+
)
34+
SELECT
35+
subquery.*
36+
FROM (
37+
SELECT
38+
benchmark_result_type_id,
39+
benchmark_type_id,
40+
array_to_json(array_agg(br.id)) AS ids
41+
FROM (
42+
SELECT id FROM (
43+
SELECT
44+
ROW_NUMBER() OVER(PARTITION BY w.weekstart ORDER BY c.created_at) AS row_num,
45+
id
46+
FROM weeks w
47+
INNER JOIN commits c
48+
ON w.weekstart = date_trunc('week', c.created_at) AND c.repo_id = #{self.id}
49+
) x
50+
WHERE row_num = 1
51+
) cw
52+
INNER JOIN benchmark_runs br
53+
ON cw.id = br.initiator_id AND br.initiator_type = 'Commit'
54+
INNER JOIN benchmark_types bt
55+
ON bt.id = br.benchmark_type_id AND bt.repo_id = #{self.id}
56+
GROUP BY benchmark_type_id, benchmark_result_type_id
57+
) AS subquery
58+
INNER JOIN benchmark_types
59+
ON benchmark_types.id = subquery.benchmark_type_id
60+
INNER JOIN benchmark_result_types
61+
ON benchmark_result_types.id = subquery.benchmark_result_type_id
62+
ORDER BY category, name
63+
SQL
64+
65+
results = self.class.connection.execute(query).to_a
66+
results.each do |row|
67+
row['ids'] = JSON.parse(row['ids'])
68+
end
69+
70+
types = self.benchmark_types
71+
.where(id: results.map { |row| row['benchmark_type_id'] }.uniq)
72+
.map { |type| [type.id, type] }.to_h
73+
result_types = BenchmarkResultType
74+
.where(id: results.map { |row| row['benchmark_result_type_id'] }.uniq)
75+
.map { |res_type| [res_type.id, res_type] }.to_h
76+
all_runs = BenchmarkRun
77+
.select(:id, :initiator_id, :result, :initiator_type, 'c.created_at')
78+
.joins("JOIN commits c ON c.id = benchmark_runs.initiator_id AND benchmark_runs.initiator_type = 'Commit'")
79+
.where(id: results.map { |row| row['ids'] }.flatten.uniq)
80+
.map { |run| [run.id, run] }.to_h
81+
82+
results.each do |res|
83+
type = types[res['benchmark_type_id']]
84+
result_type = result_types[res['benchmark_result_type_id']]
85+
runs = all_runs.values_at(*res['ids']).sort_by(&:created_at)
86+
next if !type || !result_type || runs.size == 0
87+
88+
chart_builder = ChartBuilder.new(runs, result_type).build_columns
89+
charts[type.category] ||= []
90+
charts[type.category] << {
91+
benchmark_result_type: result_type.name,
92+
columns: chart_builder.columns
93+
}
3794
end
3895

3996
$redis.setex("sparklines:#{self.id}", 1800, charts.to_msgpack)

test/models/repo_test.rb

Lines changed: 106 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,110 @@
11
require 'test_helper'
22

33
class RepoTest < ActiveSupport::TestCase
4-
# test "the truth" do
5-
# assert true
6-
# end
4+
test '#generate_sparkline_data picks first commit from every week' do
5+
repo = create(:repo)
6+
7+
mem_res_type = create(:benchmark_result_type, name: 'Memory', unit: 'rss')
8+
ips_res_type = create(:benchmark_result_type, name: 'Ips', unit: 'i/s')
9+
10+
type1 = create(:benchmark_type, repo: repo, category: 'Array map')
11+
type2 = create(:benchmark_type, repo: repo, category: 'String to_i')
12+
13+
# Week of Mon 18-05-2020 to Sun 24-05-2020
14+
c1 = create(:commit, repo: repo, created_at: Time.utc(2020, 5, 24, 1))
15+
c2 = create(:commit, repo: repo, created_at: Time.utc(2020, 5, 24, 1, 1))
16+
c3 = create(:commit, repo: repo, created_at: Time.utc(2020, 5, 24, 1, 1, 1))
17+
18+
# Week of Mon 25-05-2020 to Sun 31-05-2020
19+
c4 = create(:commit, repo: repo, created_at: Time.utc(2020, 5, 26))
20+
c5 = create(:commit, repo: repo, created_at: Time.utc(2020, 5, 29))
21+
c6 = create(:commit, repo: repo, created_at: Time.utc(2020, 5, 30))
22+
23+
# Week of Mon 01-06-2020 to Sun 07-06-2020
24+
c7 = create(:commit, repo: repo, created_at: Time.utc(2020, 6, 1))
25+
c8 = create(:commit, repo: repo, created_at: Time.utc(2020, 6, 2))
26+
c9 = create(:commit, repo: repo, created_at: Time.utc(2020, 6, 7))
27+
28+
commits = [c1, c2, c3, c4, c5, c6, c7, c8, c9]
29+
commits.each_with_index do |commit, index|
30+
[type1, type2].each do |type|
31+
create(
32+
:benchmark_run,
33+
initiator_id: commit.id,
34+
initiator_type: 'Commit',
35+
result: { rss_kb: commit.id },
36+
benchmark_result_type_id: mem_res_type.id,
37+
benchmark_type_id: type.id
38+
)
39+
create(
40+
:benchmark_run,
41+
initiator_id: commit.id,
42+
initiator_type: 'Commit',
43+
result: { bench_1: commit.id, bench_2: commit.id + 1 },
44+
benchmark_result_type_id: ips_res_type.id,
45+
benchmark_type_id: type.id
46+
)
47+
end
48+
end
49+
50+
# assert_equal([0.0, 3.0, 7.0], [index_of_c1, index_of_c4, index_of_c7])
51+
# We should pick the first commit from each week.
52+
# Since the commits are spread over a period of 3
53+
# weeks, we should have 3 commits. These commits
54+
# should be c1, c4 and c7.
55+
# We will then pick the benchmark_runs records whose
56+
# initiator_ids are the commits we picked up earlier.
57+
data = repo.generate_sparkline_data
58+
assert_equal(
59+
data,
60+
'Array map' => [
61+
{
62+
benchmark_result_type: 'Ips',
63+
columns: [
64+
{
65+
name: 'bench_1',
66+
data: [c1.id, c4.id, c7.id]
67+
},
68+
{
69+
name: 'bench_2',
70+
data: [c1.id + 1, c4.id + 1, c7.id + 1]
71+
}
72+
],
73+
},
74+
{
75+
benchmark_result_type: 'Memory',
76+
columns: [
77+
{
78+
name: 'rss_kb',
79+
data: [c1.id, c4.id, c7.id]
80+
}
81+
]
82+
}
83+
],
84+
'String to_i' => [
85+
{
86+
benchmark_result_type: 'Ips',
87+
columns: [
88+
{
89+
name: 'bench_1',
90+
data: [c1.id, c4.id, c7.id]
91+
},
92+
{
93+
name: 'bench_2',
94+
data: [c1.id + 1, c4.id + 1, c7.id + 1]
95+
}
96+
],
97+
},
98+
{
99+
benchmark_result_type: 'Memory',
100+
columns: [
101+
{
102+
name: 'rss_kb',
103+
data: [c1.id, c4.id, c7.id]
104+
}
105+
]
106+
}
107+
]
108+
)
109+
end
7110
end

0 commit comments

Comments
 (0)