Advertisement
m1dnight

Untitled

Mar 29th, 2014
325
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Erlang 10.27 KB | None | 0 0
  1. %%%-------------------------------------------------------------------
  2. %%% @author Christophe De Troyer
  3. %%% @copyright (C) 2014
  4. %%% @doc
  5. %%% Module that will run a few load tests on the Erlang project
  6. %%% @end
  7. %%% Created : 11. Mar 2014 5:07 PM
  8. %%%-------------------------------------------------------------------
  9.  
  10. % TODO LIST
  11. % TODO Proper print server load params
  12. -module(load).
  13. -author("Christophe De Troyer").
  14.  
  15. % Compile flags
  16. -compile([debug_info]).
  17.  
  18. %**************************************************************************************************
  19. % Run from terminal:
  20. % erl -noshell -eval 'load:start(50,10,5,1,1, 5)' -eval 'init:stop()'
  21.  
  22. %**************************************************************************************************
  23. % Loop the server
  24. -export([% Pubilc
  25.   start/6,
  26.   % Private
  27.   get_timeline_for_all_users/2, get_timeline_for_user/2, register_users/2,
  28.   subscribe_to_users/3, get_tweets_for_all_users/2, get_tweets_for_user/2,
  29.   spam_tweets/2, user_tweet_loop/2, wait_for_tweets_finish/1, begin_load/1]).
  30.  
  31. %**************************************************************************************************
  32. % This is the function that will start the load
  33.  
  34. start(NumberOfUsers, NumberOfSubscriptions, TweetsPerUser, TimelineReqsPerUser, AllTweetsReqPerUser, MaximumUsersPerDataActor) ->
  35.   % Create dictionary with the parameters
  36.   Params = [{number_of_users, NumberOfUsers}, {number_of_subscriptions, NumberOfSubscriptions},
  37.             {tweets_per_user, TweetsPerUser}, {tl_req_per_user, TimelineReqsPerUser},
  38.             {alltweets_req_per_user, AllTweetsReqPerUser}, {users_per_dataactor, MaximumUsersPerDataActor}],
  39.   ParamDict = dict:from_list(Params),
  40.   begin_load(ParamDict).
  41.  
  42.  
  43. begin_load(ParamDict) ->
  44.     register(shell, self()),
  45.     List = setup_server(ParamDict),
  46.     benchmark_server(List, ParamDict),
  47.     clean_server(),
  48.     ok.
  49.  
  50. total_tweets_stored() ->
  51.     data_actor_manager ! {self(), count_total_tweets},
  52.     receive
  53.       {total_tweets, Total} -> Total
  54.     end,
  55.     ok.
  56.  
  57. %**************************************************************************************************
  58. % Initiate Server
  59.  
  60. % This code is specific to the implementation of the backend. So it is probably best changed by
  61. % the user of this code.
  62. setup_server(ParamDict) ->
  63.     printing:printLoadTestParameters(dict:fetch(number_of_users, ParamDict), dict:fetch(number_of_subscriptions, ParamDict), dict:fetch(tweets_per_user, ParamDict)),
  64.     % Setup the sever back end
  65.     server_single_actor:initialize(dict:fetch(users_per_dataactor, ParamDict)),
  66.     % Register NUMBER_OF_USERS with the data_actor_manager
  67.     {Time, UserEntryPids} = timer:tc(?MODULE, register_users, [dict:fetch(number_of_users, ParamDict), []]),
  68.     io:fwrite("~p * Users registered in ~p seconds~n", [self(), Time/ 1000000]),
  69.    
  70.     % Subscribe to random users
  71.     subscribe_to_random_users(UserEntryPids, dict:fetch(number_of_users, ParamDict), dict:fetch(number_of_subscriptions, ParamDict)),
  72.     io:fwrite("~p * All subscriptions made!~n", [self()]),
  73.     UserEntryPids.
  74.  
  75. %**************************************************************************************************
  76. % End the server properly
  77. clean_server() ->
  78.     io:fwrite("~p * Unregistering data_actor_manager @ ~p~n", [self(), whereis(data_actor_manager)]),
  79.     %unregister(data_actor_manager),
  80.     io:fwrite("~p * Sending kill signal to backend~n", [self()]),
  81.     data_actor_manager ! {kill},
  82.     io:fwrite("~p * Unregistering shell @ ~p~n", [self(), whereis(shell)]),
  83.     unregister(shell),
  84.     ok.
  85.  
  86.  
  87. %**************************************************************************************************
  88. % Server load
  89. benchmark_server(UserList, ParamDict) ->
  90.     {Time, _} = timer:tc(?MODULE, spam_tweets, [UserList, ParamDict]),
  91.     io:fwrite("~p * Sent  tweets in ~p seconds~n", [self(), Time/ 1000000]),
  92.  
  93.     {Time2, _} = timer:tc(?MODULE, get_tweets_for_all_users, [UserList, ParamDict]),
  94.     io:fwrite("~p * Got all tweets for all users in ~p seconds~n", [self(), Time2/ 1000000]),
  95.  
  96.     {Time3, _} = timer:tc(?MODULE, get_timeline_for_all_users, [UserList, ParamDict]),
  97.     io:fwrite("~p * Got timeline for all users in ~p seconds~n", [self(), Time3/ 1000000]),
  98.  
  99.     %("Writing stats to file..~n"),
  100.     % Server parameters and statistics
  101.     % TotalTweetsOnServer          = total_tweets_stored(),
  102.     NumberOfSchedulers           = erlang:system_info(schedulers_online),
  103.     NumberOfTweetsPerUser        = dict:fetch(tweets_per_user, ParamDict),
  104.     NumberOfUsers                = dict:fetch(number_of_users, ParamDict),
  105.     SubscriptionsPerUser         = dict:fetch(number_of_subscriptions, ParamDict),
  106.     TotalTimelineRequestsPerUser = dict:fetch(tl_req_per_user, ParamDict),
  107.     TotalTweetsRequetsPerUser    = dict:fetch(alltweets_req_per_user, ParamDict),
  108.     UserPerDataActor             = dict:fetch(users_per_dataactor, ParamDict),
  109.     % Write statistics to output file
  110.     % writeStatsToFile(NumberOfCores, NumberOfTweets, NumberOfUsers, Miliseconds)
  111.     write_to_file:writeTweetPerformance(NumberOfSchedulers,
  112.                                         NumberOfTweetsPerUser,
  113.                                         NumberOfUsers,
  114.                                         UserPerDataActor,
  115.                                         Time / 1000),
  116.     write_to_file:writeFetchTweetsReqPerformance(
  117.                                         NumberOfSchedulers,
  118.                                         NumberOfTweetsPerUser,
  119.                                         NumberOfUsers,
  120.                                         TotalTweetsRequetsPerUser,
  121.                                         UserPerDataActor,
  122.                                         Time2 / 1000),
  123.     write_to_file:writeFetchTimelineReqPerformance(
  124.                                         NumberOfSchedulers,
  125.                                         NumberOfTweetsPerUser,
  126.                                         NumberOfUsers,
  127.                                         TotalTimelineRequestsPerUser,
  128.                                         SubscriptionsPerUser,
  129.                                         UserPerDataActor,
  130.                                         Time3 / 1000),  
  131.  
  132.     io:fwrite("~p * Benchmarking done! ~n", [self()]),
  133.     ok.
  134.  
  135. %**************************************************************************************************
  136. % Register Users
  137.  
  138. %Function that loops until the number of registrations is met
  139. register_users(0, UserEntryPids) -> UserEntryPids;
  140. register_users(N, UserEntryPids) ->
  141.   NewUser = server_single_actor:register_user(),
  142.   register_users(N - 1, [NewUser | UserEntryPids]).
  143.  
  144. %**************************************************************************************************
  145. % Subscribe to users
  146.  
  147. %Subscribe to random users using a random generated list
  148. subscribe_to_random_users([], NumberOfUsers, _) ->
  149.   waitForSubscriptionsToFinish(NumberOfUsers),
  150.   ok;
  151. subscribe_to_random_users([User | Rest], NumberOfUsers, NumberOfSubscriptions) ->
  152.   UsersToSubscribeTo = helpers:createRandomList(1, NumberOfUsers, NumberOfSubscriptions),
  153.   spawn(?MODULE, subscribe_to_users, [UsersToSubscribeTo, User, self()]),
  154.   subscribe_to_random_users(Rest, NumberOfUsers, NumberOfSubscriptions).
  155.  
  156. waitForSubscriptionsToFinish(0) -> ok;
  157. waitForSubscriptionsToFinish(N) ->
  158.   receive
  159.     {done_subscribing} -> waitForSubscriptionsToFinish(N -1)
  160.   end.
  161.  
  162. subscribe_to_users([],{_UserId, _EntryPid}, CommanderPid) ->
  163.   CommanderPid ! {done_subscribing},
  164.   ok;
  165. subscribe_to_users([UserIdToSubscribeTo | SubscribeTos], {UserId, EntryPid}, CommanderPid) ->
  166.   server_single_actor:subscribe(EntryPid, UserId, UserIdToSubscribeTo),
  167.   subscribe_to_users(SubscribeTos, {UserId, EntryPid}, CommanderPid).
  168.  
  169.  
  170.  
  171. %**************************************************************************************************
  172. % Request the timeline for each user
  173.  
  174. get_timeline_for_all_users(UserList, ParamDict) ->
  175.     lists:map(fun(User) ->
  176.             spawn(?MODULE, get_timeline_for_user, [User, dict:fetch(tl_req_per_user, ParamDict)])
  177.           end,
  178.           UserList),
  179.     wait_for_finish_get_timeline(length(UserList)),
  180.     ok.
  181.  
  182. get_timeline_for_user(_, 0) ->
  183.     shell ! {got_timeline},
  184.     ok;
  185. get_timeline_for_user({UserId, EntryPid}, N) ->
  186.     Tweets = server:get_timeline(EntryPid, UserId, 1),
  187.     %io:fwrite("Timeline: ~p~n", [length(Tweets)]),
  188.     get_timeline_for_user({UserId, EntryPid}, N -1).
  189.  
  190.  
  191. wait_for_finish_get_timeline(0) -> ok;
  192. wait_for_finish_get_timeline(N) ->
  193.     receive
  194.         {got_timeline} -> wait_for_finish_get_timeline(N -1)
  195.     end.
  196.  
  197. %**************************************************************************************************
  198. % Get All tweets by a certain user
  199.  
  200. get_tweets_for_all_users(UserList, ParamDict) ->
  201.     lists:map(fun(User) ->
  202.             spawn(?MODULE, get_tweets_for_user, [User, dict:fetch(alltweets_req_per_user, ParamDict)])
  203.           end,
  204.           UserList),
  205.     wait_for_finish_get_tweets(dict:fetch(number_of_users, ParamDict)),
  206.     ok.
  207.  
  208. get_tweets_for_user(_, 0) ->
  209.     shell ! {got_tweets},
  210.     ok;
  211. get_tweets_for_user({UserId, EntryPid}, N) ->
  212.     Tweets = server:get_tweets(EntryPid, UserId, 1),
  213.     %io:fwrite("Tweets: ~p~n", [length(Tweets)]),
  214.     get_tweets_for_user({UserId, EntryPid}, N -1).
  215.    
  216.  
  217. wait_for_finish_get_tweets(0) -> ok;
  218. wait_for_finish_get_tweets(N) ->
  219.     receive
  220.         {got_tweets} -> wait_for_finish_get_tweets(N -1)
  221.     end.
  222.  
  223.  
  224. %***************************************** Tweet Spamming   ***************************************
  225. % Spam the server with a lot of tweets
  226. spam_tweets(UserList, ParamDict) ->
  227.     lists:map(fun(User) ->
  228.                 spawn(?MODULE, user_tweet_loop, [User,dict:fetch(tweets_per_user, ParamDict)])
  229.               end,
  230.               UserList),
  231.  
  232.     wait_for_tweets_finish(dict:fetch(number_of_users, ParamDict)),
  233.     ok.
  234.  
  235. wait_for_tweets_finish(0) -> ok;
  236. wait_for_tweets_finish(N) ->
  237.     receive
  238.         {done_spawning_tweeters} -> wait_for_tweets_finish(N -1)
  239.     end.    
  240.  
  241. user_tweet_loop(_, 0) ->
  242.     shell ! {done_spawning_tweeters};
  243.  
  244. user_tweet_loop({UserId, EntryPid}, Counter) ->
  245.     _Timestamp = server:tweet(EntryPid, UserId, io_lib:fwrite("Tweet from ~p. (~p)", [UserId, Counter])),
  246.     user_tweet_loop({UserId, EntryPid}, Counter - 1).
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement