% coding: utf-8 % Copyright 2008 Grégory Burri % % This file is part of Euphorik. % % Euphorik is free software: you can redistribute it and/or modify % it under the terms of the GNU General Public License as published by % the Free Software Foundation, either version 3 of the License, or % (at your option) any later version. % % Euphorik is distributed in the hope that it will be useful, % but WITHOUT ANY WARRANTY; without even the implied warranty of % MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the % GNU General Public License for more details. % % You should have received a copy of the GNU General Public License % along with Euphorik. If not, see . % % Module de test de euphorik. % Crée un certain nombre d'utilisateur et post des messages aléatoire. -module(euphorik_test). -export([ bench_write_minichat/1, start/2, stop/1, bench_get_messages/0, bench_get_messages_avec_2_conversations/0 ]). -include("../include/euphorik_bd.hrl"). % les intervalles en seconde min en max entre deux postes de message d'un utilisateur % le temps d'attente est choisi au hasard entre ces deux valeurs -define(INTERVALLE_MIN, 2). -define(INTERVALLE_MAX, 5). % N est le nombre d'utilisateur % M est le nombre de message que chaque utilisateur va poster start(N, M) -> Ids = creer_users(N), lists:map( fun(Id) -> timer:sleep(100), spawn( fun() -> {A1, A2, A3} = erlang:timestamp(), random:seed(A1, A2, A3), loop(Id, M) end ) end, Ids ). stop(Pids) -> lists:foreach(fun(Pid) -> exit(Pid, kill) end, Pids). % des trucs qui trainent bench_get_messages() -> T = [ {page,"chat"}, {cookie,"5G84A5CJXMCPEHNI8T5A9"}, {message_count,40}, {last_message_id,0}, {main_page,1}, {conversations,{array,[]}} ], moyenne_temps(euphorik_protocole, wait_event, [T], 20). bench_get_messages_avec_2_conversations() -> T = [ {page,"chat"}, {cookie,"5G84A5CJXMCPEHNI8T5A9"}, {message_count,40}, {last_message_id,0}, {main_page,1}, {conversations,{array, [ {struct, [ {root, 921}, {page,1}, {last_message_id,0} ]}, {struct, [ {root, 772}, {page, 1}, {last_message_id, 0} ]} ]}} ], moyenne_temps(euphorik_protocole, wait_event, [T], 20). moyenne_temps(Module, Fun, Args, N) -> moyenne_temps(Module, Fun, Args, N, N, 0). moyenne_temps(_, _, _, 0, Total, Temps_acc) -> Temps_acc / Total; moyenne_temps(Module, Fun, Args, N, Total, Temps_acc) -> {Temps, _} = timer:tc(Module, Fun, Args), moyenne_temps(Module, Fun, Args, N - 1, Total, Temps_acc + Temps). % Crée N user avec des noms aléatoires et renvoie la liste des id. creer_users(N) -> creer_users(N, []). creer_users(0, Ids) -> lists:map(fun(#user{id = Id}) -> Id end, Ids); creer_users(N, Ids) -> creer_users(N - 1, [euphorik_bd:nouveau_user(mot_rand(random:uniform(4) + 4), "", "", #profile{}) | Ids ]). % crée un message aléatoire et le renvoie message_rand() -> lists:flatten(message_rand(random:uniform(10), [])). message_rand(0, Mots) -> Mots; message_rand(N, Mots) -> message_rand(N - 1, [mot_rand(random:uniform(2) + 5), $ | Mots]). % Renvoie une succession de lettre aléatoire mot_rand(L) -> mot_rand(L, []). mot_rand(0, Mot) -> Mot; mot_rand(L, Mot) -> mot_rand(L - 1, [random:uniform($z - $a + 1) + $a - 1 | Mot]). % Tire au hasard de 0 à 3 messages sur les 10 derniers postés, renvoie une liste de int() % répartition : % 0 : 0.1 % 1 : 0.95 % 2 : 0.04 % 3 : 0.01 messages_id_rand() -> R = random:uniform(), if R =< 0.1 -> []; true -> Messages = lists:map(fun(#minichat{id = Id}) -> Id end, euphorik_bd:messages(8)), if R > 0.1 andalso R =< 0.95 -> tire_element_rand(1, Messages); R > 0.95 andalso R =< 0.99 -> tire_element_rand(2, Messages); true -> tire_element_rand(3, Messages) end end. % tire N element distinct parmis la liste L proposée tire_element_rand(N, L) when N =< length(L) -> tire_element_rand(N, L, []); tire_element_rand(_, _) -> []. tire_element_rand(0, _, Elements) -> Elements; tire_element_rand(N, L, Elements) -> E = lists:nth(random:uniform(length(L)), L), E_se_trouve_dans_Elements = lists:any(fun(E2) -> E2 =:= E end, Elements), if E_se_trouve_dans_Elements -> % si E a déjà été tiré on recommence sans rien changer tire_element_rand(N, L, Elements); true -> tire_element_rand(N-1, L, [E | Elements]) end. loop(User_id, 0) -> io:format("~p a fini~n", [User_id]); loop(User_id, M) -> % attend un temp aléatoire compris entre INTERVALLE_MIN sec et INTERVALLE_MAX sec timer:sleep(1000 * (random:uniform(?INTERVALLE_MAX - ?INTERVALLE_MIN + 1) + ?INTERVALLE_MIN - 1)), % poste un message aléatoire par une personne aléatoire répondant à des messages aléatoires {Message, Repond_a} = {message_rand(), messages_id_rand()}, % io:format("~p poste ~p et repond a ~w~n", [User_id, Message, Repond_a]), case euphorik_bd:nouveau_message(Message, User_id, Repond_a) of {erreur, E} -> io:format("~p : erreur : ~p~n", [User_id, E]), loop(User_id, M); _ -> loop(User_id, M - 1) end. % Permet de tester la vitesse d'écriture en fonction de la % taille de la BD % voir : http://erlang.org/pipermail/erlang-questions/2008-October/038697.html bench_write_minichat(Filename) -> Times = bench_write_minichat(1, []), {ok, File} = file:open(Filename, [write]), lists:foreach( fun({Id, Time}) -> io:format(File, "~w ~w~n", [Id, Time]) end, Times ), file:close(File). bench_write_minichat(100000, Temps) -> Temps; bench_write_minichat(N, Temps) -> {T, _} = timer:tc(mnesia, transaction, [fun() -> Id = mnesia:dirty_update_counter(counter, minichat, 1), mnesia:write(#minichat{ id = Id, auteur_id = random:uniform(10000), date = erlang:timestamp(), pseudo = "Test", contenu = "Blabla blabla bla.", racine_id = random:uniform(10000) }) end]), bench_write_minichat(N + 1, if N rem 500 =:= 0 -> [{N, T} | Temps]; true -> Temps end).