✂️

Split GemでABの振り分け後にキャンセルができるか調べてみた

2024/02/08に公開

調べたこと

  • SplitのABの振り分けをキャンセルができるか調べました
    • 「キャンセル」とは、再割り当てができる状態に戻すということです
  • キャンセルした場合のパターン割り振りの挙動についても調べました

対象Gem

https://github.com/splitrb/split

バージョンは4.0.3です
導入手順は割愛します
基本的には以下のメソッドでab_testの振り分けが行われます

ab_test("任意のテスト名")

結論

ABの振り分けをキャンセルができるかどうか

以下のメソッドを実行すれば無かったことにできました

ab_user.delete('#{experiments名}')

サンプル数の動作検証

しかし、サンプル数(Split内ではparticipants)のカウントは変わりません

[49] pry(main)> ab_test("dummy")  
=> "new" # newパターンに割り振られた

[51] pry(main)> Split.redis.hgetall("dummy:new")
=> {"participant_count"=>"1"} # dummy experimentsのnewパターンのカウントが1増えた

[52] pry(main)> ab_user.delete("dummy") # abテストをキャンセルしたが
=> 1

[53] pry(main)> Split.redis.hgetall("dummy:new") # 数に変化は無い
=> {"participant_count"=>"1"}

[54] pry(main)> ab_test("dummy") # 改めてabテスト開始し、newパターンに割り振られた
=> "new"

[55] pry(main)> Split.redis.hgetall("dummy:new") # 数は増加
=> {"participant_count"=>"2"}

そのため数を直接変更したい場合はhashをredisに入力することで実現しました

Split.redis.hset("dummy:new", 'participant_count', 100)

キャンセルした場合の割り振りの挙動

考えられる挙動は2パターンありました

  1. 現在のサンプル数と割合を見比べてバランスを取るように調整する
      • 1:1の場合100人:101人になったときには、101人:101人になるようなロジック
  2. サンプル数を全く見ずに割合だけで割り振る
    • 確率でそのうち収束する

結論

  • 2
    • 割合だけでABを割り振っていました

調査内容

何もしていないケースと、実際にRedis内の値をいじったケースで見比べてみました

何もしていないケース

1000回、ABテストの割り振りを行ないます

dummyの配分は1:1です

[1] pry(main)> 1000.times do
[1] pry(main)*   ab_test("dummy")
[1] pry(main)*   ab_user.delete("dummy")
[1] pry(main)* end  
=> 1000
[2] pry(main)> Split.redis.hgetall("dummy:new")
=> {"participant_count"=>"489"}
[3] pry(main)> Split.redis.hgetall("dummy:default")
=> {"participant_count"=>"511"}

概ね1:1で割り振られています

値を加工したケース

あらかじめ値を変更して、先程の処理を実行します

[1] pry(main)> $split_redis.hset("dummy:default", {"participant_count" => 500})
=> 1
[2] pry(main)> $split_redis.hgetall("dummy:default")
=> {"participant_count"=>"500"}
[1] pry(main)> 1000.times do
[1] pry(main)*   ab_test("dummy")  
[1] pry(main)*   ab_user.delete("dummy")  
[1] pry(main)* end  
=> 1000
[2] pry(main)> $split_redis.hgetall("dummy:default")
=> {"participant_count"=>"979"}
[3] pry(main)> $split_redis.hgetall("dummy:new")
=> {"participant_count"=>"521"}

値の調整はされず、純粋に約500ずつ増えただけとなりました

この結果から、Splitは純粋に設定した割合に応じてランダムに割り振っているだけということがわかりました

SMARTCAMP Engineer Blog

Discussion