Skip to content

Commit 87fbd83

Browse files
patblandrew
authored andcommitted
Allow configuration of how often winning alternatives are recalculated (#501)
* Rubocop: Update obsolete rule names I saw these warnings on Rubocop 0.50.0: Error: The `Style/MethodCallParentheses` cop has been renamed to `Style/MethodCallWithoutArgsParentheses`. (obsolete configuration found in /Users/pat/academia/projects/split/.rubocop.yml, please update it) The `Style/OpMethods` cop has been renamed and moved to `Naming/BinaryOperatorParameter`. (obsolete configuration found in /Users/pat/academia/projects/split/.rubocop.yml, please update it) * Allow configuration of how often winning alternatives are recalculated If you're running A/B tests for a short period of time, the "Probability of being Winner" numbers can be unhelpful or misleading.
1 parent edf83e9 commit 87fbd83

File tree

4 files changed

+17
-6
lines changed

4 files changed

+17
-6
lines changed

.rubocop.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -716,7 +716,7 @@ Style/LineEndConcatenation:
716716
line end.
717717
Enabled: false
718718

719-
Style/MethodCallParentheses:
719+
Style/MethodCallWithoutArgsParentheses:
720720
Description: 'Do not use parentheses for method calls with no arguments.'
721721
StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#no-args-no-parens'
722722
Enabled: false
@@ -816,7 +816,7 @@ Style/OneLineConditional:
816816
StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#ternary-operator'
817817
Enabled: false
818818

819-
Style/OpMethod:
819+
Naming/BinaryOperatorParameter:
820820
Description: 'When defining binary operators, name the argument other.'
821821
StyleGuide: 'https://github.com/bbatsov/ruby-style-guide#other-arg'
822822
Enabled: false

README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,14 @@ As per this [blog post](http://www.evanmiller.org/how-not-to-run-an-ab-test.html
115115

116116
The second option uses simulations from a beta distribution to determine the probability that the given alternative is the winner compared to all other alternatives. You can view these probabilities by clicking on the drop-down menu labeled "Confidence." This option should be used when the experiment has more than just 1 control and 1 alternative. It can also be used for a simple, 2-alternative A/B test.
117117

118+
Calculating the beta-distribution simulations for a large number of experiments can be slow, so the results are cached. You can specify how often they should be recalculated (the default is once per day).
119+
120+
```ruby
121+
Split.configure do |config|
122+
config.winning_alternative_recalculation_interval = 3600 # 1 hour
123+
end
124+
```
125+
118126
## Extras
119127

120128
### Weighted alternatives

lib/split/configuration.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ class Configuration
2525
attr_accessor :on_before_experiment_delete
2626
attr_accessor :include_rails_helper
2727
attr_accessor :beta_probability_simulations
28+
attr_accessor :winning_alternative_recalculation_interval
2829
attr_accessor :redis
2930

3031
attr_reader :experiments
@@ -217,6 +218,7 @@ def initialize
217218
@algorithm = Split::Algorithms::WeightedSample
218219
@include_rails_helper = true
219220
@beta_probability_simulations = 10000
221+
@winning_alternative_recalculation_interval = 60 * 60 * 24 # 1 day
220222
@redis = ENV.fetch(ENV.fetch('REDIS_PROVIDER', 'REDIS_URL'), 'redis://localhost:6379')
221223
end
222224

lib/split/experiment.rb

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -262,10 +262,11 @@ def load_from_redis
262262
end
263263

264264
def calc_winning_alternatives
265-
# Super simple cache so that we only recalculate winning alternatives once per day
266-
days_since_epoch = Time.now.utc.to_i / 86400
265+
# Cache the winning alternatives so we recalculate them once per the specified interval.
266+
intervals_since_epoch =
267+
Time.now.utc.to_i / Split.configuration.winning_alternative_recalculation_interval
267268

268-
if self.calc_time != days_since_epoch
269+
if self.calc_time != intervals_since_epoch
269270
if goals.empty?
270271
self.estimate_winning_alternative
271272
else
@@ -274,7 +275,7 @@ def calc_winning_alternatives
274275
end
275276
end
276277

277-
self.calc_time = days_since_epoch
278+
self.calc_time = intervals_since_epoch
278279

279280
self.save
280281
end

0 commit comments

Comments
 (0)