Comments 46
Мне даже как-то неловко вам это говорить, но ngx_http_split_clients_module способ более гибкий и менее ресурсоёмкий.
Менее ресурсоёмкий по сравнению с хранением переменной в сессии? (которая в 99.9% случаев так и так создана)
Менее ресурскоёмкий, чем хранение последнего посетителя в базе.
Если есть задача гарантированно выдавать «не то, что было последнему», то без персистентого хранилища вы не обойдётесь никак. Модуль nginx распределяет пользователей согласно выбранных вероятностей и не гарантирует, что каждому последуюшему посетителю будет выдано не то, что предыдущему.
Я понимаю, что в реальной жизни такое требование вряд ли будет, но просто решения не эквивалентны. И если требование изменить на стандартные вероятности — тогда получим тот же самый rand() + сессию.
Я понимаю, что в реальной жизни такое требование вряд ли будет, но просто решения не эквивалентны. И если требование изменить на стандартные вероятности — тогда получим тот же самый rand() + сессию.
На больших числах распределение будет равномерное. Проверено.
Впрочем, вы об этом уже написали, как я погляжу.
Впрочем, вы об этом уже написали, как я погляжу.
Неужели вы думаете, что один дополнительный элементарный запрос к БД завалит магазин нагрузкой?
Как справедливо сказал автор выше — база вам не нужна, достаточно rand() > 0.5? 'A': 'B' и класть в сессию.
т.е. если я 100 раз запущу rand() > 0.5? 'A': 'B', то появления A и B будут в равных долях?
При условии, что rand() возвращает от 0 до 1 — да. Чем больше, тем распределение будет ближе к 1:1
$results = array('A' => 0, 'B' => 0);
$i = 1000;
while ($i--) {
$results[ mt_rand(1, 100) > 50 ? 'A' : 'B' ]++;
}
var_dump($results);
Бррр, как-то странно тэг «code» работает :-S
При таком подходе разница между A и B может достигать 15%, это существенная разница
Не придирайтесь, я ведь сказал «может» относительно вашего кода в 1000 итераций. Согласен, что распределение зависит от кол-ва операций, но даже на 1М я вижу разницу в 3%.
Да, заменив запрос к БД на rand() вы незначительно сократите нагрузку на сервер и немного упростите код, но ценой будет погрешность в анализе. Думаю оно того не стоит.
Да, заменив запрос к БД на rand() вы незначительно сократите нагрузку на сервер и немного упростите код, но ценой будет погрешность в анализе. Думаю оно того не стоит.
3% на 1М запусков? Вы уверены, что правильно посчитали?
> незначительно
Значительно. Разница между вызовом rand() и Выполнением SQL + DML огромна.
> незначительно
Значительно. Разница между вызовом rand() и Выполнением SQL + DML огромна.
Конечно же это воспроизводится не каждый раз, но я вижу такую цифру (при 1М запусков)
var_dump($results['A']/$results['B']);
//float 0.97199816833671
В то время как разница считается вот так:
Позапускайте и посмотрите на эту цифру теперь
var_dump(abs($results['A'] - $results['B']) / 10000);
Позапускайте и посмотрите на эту цифру теперь
ps: так или иначе — в течение двух минут запускал свой код автоматически (получилось около 300 запусков), так и не смог получить отношение в 0.97 как у вас. Непруха :-(
Подождите, а вы хоть понимаете смысл а/б тестирования? Вам не важно, чтоб 500 человек увидели надпись, а 500 не увидели. Вам важно сравнить поведение на больших массивах клиентов.
Так для этого будет сессия. Тут обсуждают как раздать эти сессии посетителям примерно поровну.
В том то и дело, что здесь почему то уперлись в «равные доли». на самом деле они нафиг не надо. Важно чтоб возрастной, половой, териториальный и т.д. состав групп был одинаковый. Если эти условия выполнены — то пофиг, в равных долях у вас разделилось или нет. Потому что на выходе у вас должно быть чтото типа «Группа А: конверсия 4%», «Группа Б: конверсия 5%».
таки вам критично чтоб было 50/50? 49/51 уже никак?
Одна мысль пришла. Можно действительно делить на группы рандомно. И не важно какое соотношение будет. Пусть даже 100/1000. Но посчитать тогда нужно именно ПРОЦЕНТ заказвших в той или иной группе, т.е. внутри группы. Допустим группа А: пришли 100 человек, заказали 10. Группа Б: пришли 1000 человек, заказали 10. Из этого видно, что в А конверсия выше. А:10%, Б: 1%. Т.е. считать имено процентное соотношение заказавших к количеству посетителей внутри одной группы (А или Б).
Т.е. зашел человек, рандомно ему назначили либо А, либо Б. И тут же записали в счетчик «пришедших». «Пришедшие А» и «пришедшие Б». В итоге эти два счетчика могу показывать разные данные. В группе пришедших на сайт «А» оказалось 100 человек. А в группе «пришедших Б» оказалось 1000 человек. Да, группы, благодаря рандому получились разными, с очень большим отличием (хотя это и невозможно, но допустим). Теперь мы должны считать сколько заказов сделали пользователи из группы А и из группы Б. Т.е. для этого тоже нужны два счетчика: «заказавшие А» и «заказавшие Б». И в итоге по результатам тестирования берем отношение (процент) «заказавших А» к «пришедшим А» и «заказавших Б» и «пришедшим Б». Сравниваем полученные проценты. И пофиг нам что группы были разными по количеству.
Получается в данном случае мы точно защищаем себя от каких то случайных статистических последовательностей (типа той, что каждый второй посетитель — это женщина). Группы будут очень смешанными и разносторонними по географическому признаку, половому, возрастному и т.д.
Получается в данном случае мы точно защищаем себя от каких то случайных статистических последовательностей (типа той, что каждый второй посетитель — это женщина). Группы будут очень смешанными и разносторонними по географическому признаку, половому, возрастному и т.д.
я сейчас, видимо, жутко туплю, но почему rand() > 0.5 ??
разве rand() генерирует число от 0 до 0,9?
разве rand() генерирует число от 0 до 0,9?
Тоесть я два раза зашёл — побывал А и Б? Я думаю всё таки стоит как минимум в куку писать. Зарегистрированным и вообще лучше в базу
Вот и я об этом думаю? Не знаю как правильно. Эти тонкости должны быть известны только тем кто глубоко эту тему копал. Кто досконально разбирается в механизмах тестирования, теории вероятности, математике и т.д.
Ну, допустим деление пользователя средствами nginx обеспечивает однозначное попадание одного пользователя в одну группу.
Но вам никто не мешает ставить куку и определять по ней дополнительно. Кроме того, зарегистрированный пользователь тоже обладает какой-нибудь кукой или переменной сессии.
Но вам никто не мешает ставить куку и определять по ней дополнительно. Кроме того, зарегистрированный пользователь тоже обладает какой-нибудь кукой или переменной сессии.
Не совсем понимаю в чем проблема использования сессий или кук? Ведь пользователи гарантированно будут делиться на две половины. Разве нет?
О чём разговор? Автор же и так записывает значение в сессию, которая основана на куке
А если у автора 5 000 запросов к сайту в секунду?
upd. Не в тот тред.
upd. Не в тот тред.
И которая как правило удаляется после закрытия браузера. Вы можете попасть в интересную ситуацию, когда пользователь начал использовать сценарий А, закрыл браузер, и продолжил покупку уже по сценарию Б. По сути — это главная притензия к решению.
Несколько дилетантских соображений:
1. Вам не нужно, чтобы каждый следующий посетитель попадал в другую группу. Вам нужно, чтобы группы были одного размера (упрощенно, при достаточном объеме групп можно нормировать показатели на размеры группы). На самом деле даже не обязательно тестировать на всей аудитории.
2. Разнесение на группы на основе четный/нечетный посетитель может быть даже вредно, особенно при небольшом количестве трафика, т.к. результат может зависеть от паттерна посещения или регистрациии. Например, заходит жена, находит товар, кидает ссылку мужу, который и осуществляет покупку. Если между ними посетителей не было, то жена попадет в одну группу, а муж — в другую.
3. Если период тестирования значительно больше времени жизни сессии, то постоянный (или несколько раз возвращающийся человек) может попадать то в одну группу, то в другую. Если при этом для каждой группы есть свой дизайн сайта, то такая «мигалка» может раздражать сама по себе. Так что лучше делать группы персистентными (на период одного тестирования).
4. Если выбирать группу для посетителей случайно, то может и не повезти (рандом такой рандом), и в составе групп могут появиться статистически значимые отклонения (по полу, количеству предыдущих покупок, возрасту, географии и т.д.). Если подготавливать группы заранее, то можно попытаться свести такие различия к минимуму. Если разносить посетителей на группы автоматически, то желательно иметь этап пост-обработки данных по окончанию тестирования, чтобы убедиться в том, что в характеристиках групп не было значительных отклонений.
1. Вам не нужно, чтобы каждый следующий посетитель попадал в другую группу. Вам нужно, чтобы группы были одного размера (упрощенно, при достаточном объеме групп можно нормировать показатели на размеры группы). На самом деле даже не обязательно тестировать на всей аудитории.
2. Разнесение на группы на основе четный/нечетный посетитель может быть даже вредно, особенно при небольшом количестве трафика, т.к. результат может зависеть от паттерна посещения или регистрациии. Например, заходит жена, находит товар, кидает ссылку мужу, который и осуществляет покупку. Если между ними посетителей не было, то жена попадет в одну группу, а муж — в другую.
3. Если период тестирования значительно больше времени жизни сессии, то постоянный (или несколько раз возвращающийся человек) может попадать то в одну группу, то в другую. Если при этом для каждой группы есть свой дизайн сайта, то такая «мигалка» может раздражать сама по себе. Так что лучше делать группы персистентными (на период одного тестирования).
4. Если выбирать группу для посетителей случайно, то может и не повезти (рандом такой рандом), и в составе групп могут появиться статистически значимые отклонения (по полу, количеству предыдущих покупок, возрасту, географии и т.д.). Если подготавливать группы заранее, то можно попытаться свести такие различия к минимуму. Если разносить посетителей на группы автоматически, то желательно иметь этап пост-обработки данных по окончанию тестирования, чтобы убедиться в том, что в характеристиках групп не было значительных отклонений.
Эти «тонкости» становятся понятными после 15 минут раздумий над проблемой (желательно вместе с маркетологом). Знаю, потому что занимался подобным.
На самом деле, Ваш код — явное частное решение проблемы. Как пример, который стоит показывать сообществу — явно не тянет. Ну а если Ваши нужды удовлетворяет — то и ладно.
На самом деле, Ваш код — явное частное решение проблемы. Как пример, который стоит показывать сообществу — явно не тянет. Ну а если Ваши нужды удовлетворяет — то и ладно.
Это всё на тему «высшее образование программисту не нужно»
Создавал аналогичную систему на php, тогда тоже думал про вариант с cookie и rand(0, 1).
В итоге организовал процесс так:
Существует пустая таблица — список пользователей для тестирования (поля: ip, вариант тестирования A/B).
Пользователь заходит — в таблице в зависимости от количества участников A/B ему выдается вариант A или B, таким образом удалось достичь 50/50%. Добавляется запись в таблицу — ip пользователя и вариант.
В итоге организовал процесс так:
Существует пустая таблица — список пользователей для тестирования (поля: ip, вариант тестирования A/B).
Пользователь заходит — в таблице в зависимости от количества участников A/B ему выдается вариант A или B, таким образом удалось достичь 50/50%. Добавляется запись в таблицу — ip пользователя и вариант.
я для А-B тестирования делал просто mt_rand(0, 1) и клал в куки. Не вижу особого смысла гнаться за ровно 50/50
Sign up to leave a comment.
Как я реализовывал А/Б-тестирование на PHP