Skip to content

Commit

Permalink
hello
Browse files Browse the repository at this point in the history
  • Loading branch information
akandratovich committed May 10, 2012
1 parent a138644 commit d9707b1
Show file tree
Hide file tree
Showing 58 changed files with 6,130 additions and 2 deletions.
4 changes: 2 additions & 2 deletions README.md
@@ -1,2 +1,2 @@
stock
=====
stocks - application
bench - benchmark script
3 changes: 3 additions & 0 deletions bench/README.md
@@ -0,0 +1,3 @@
node 2 node requests benchmark

(./pic/excel.png)
73 changes: 73 additions & 0 deletions bench/bench.erl
@@ -0,0 +1,73 @@
%% @author Andrew Kondratovich <andrew.kondratovich@gmail.com>
%% @doc Some benchmarks for stock app
%%

-module(bench).
-author('Andrew Kondratovich <andrew.kondratovich@gmail.com>').

-compile([export_all]).
% -export([perform/0]).

-define(PRICE0, 0.0).
-define(PRICE1, 2.0).
-define(VOLUME, 1000).
-define(MINUTE, (60 * 1000)).


random_price(P0, P1) ->
V = random:uniform(),
P0 + V * (P1 - P0).

random_time(F, T) ->
V = random:uniform(erlang:trunc(T - F)),
erlang:trunc(F + V).

generate_value(P0, P1, F, T, Volume) ->
{random_time(F, T), random_price(P0, P1), random:uniform(Volume)}.

generate(From, Minutes, PerMinute) ->
lists:map(fun(E) ->
generate_value(
?PRICE0,
?PRICE1,
E * ?MINUTE / PerMinute,
(E + 1) * ?MINUTE / PerMinute,
?VOLUME)
end, lists:seq(From, Minutes * PerMinute - 1)).

store(Name, Data) ->
Self = self(),
Node = node0(),
erlang:spawn(Node, fun() -> Self ! stock_api:store(Name, Data) end).

select(Name, From, To, Scale) ->
Self = self(),
Node = node0(),
erlang:spawn(Node, fun() -> Self ! stock_api:select(Name, From, To, Scale) end).

erase(Name) ->
Node = node0(),
erlang:spawn(Node, fun() -> stock_api:erase(Name) end).

node0() -> 'stocknode@127.0.0.1'.

t_store(TSize, Per) ->
Data = generate(0, TSize, Per),
{Time, _} = timer:tc(fun() ->
store("TEST_STORE", Data),
receive _ -> ok after 10000 -> timeout end
end),
Time.

t_select(Count, Scale) ->
{Time, _} = timer:tc(fun() ->
select("TEST_STORE", 0, Count * ?MINUTE, Scale),
receive _ -> ok after 10000 -> timeout end
end),
Time.

perform() ->
case net_adm:ping('stocknode@127.0.0.1') of
pang -> exit(stocknode_not_found);
_ -> c:nl(?MODULE)
end.
1 change: 1 addition & 0 deletions bench/bootstrap.sh
@@ -0,0 +1 @@
erlc bench.erl && erl -name 'stocknode-bench@127.0.0.1' -setcookie stocknode -s bench perform
Binary file added bench/pic/excel.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions stocks/README.md
@@ -0,0 +1,7 @@
rebar get-deps
rebar compile
cd rel
rebar generate
sh ./stocknode/bin/stocknode console

look at `http://localhost:8000/`
80 changes: 80 additions & 0 deletions stocks/apps/stock/src/ets_manager.erl
@@ -0,0 +1,80 @@
%% @author Andrew Kondratovich <andrew.kondratovich@gmail.com>
%% @doc ETS Manager. Used to save tables in case of process error.
%%
%% http://steve.vinoski.net/blog/2011/03/23/dont-lose-your-ets-tables/

-module(ets_manager).
-author('Andrew Kondratovich <andrew.kondratovich@gmail.com>').

-behaviour(gen_server).
-export([start/0, new/2]).
-export([
init/1,
handle_call/3,
handle_cast/2,
handle_info/2,
terminate/2,
code_change/3
]).

-define(TIMEOUT, 1000).

%%% API
start() ->
gen_server:start_link({local, ?MODULE}, ?MODULE, [], []).

%%% gen_server callbacks

init([]) -> {ok, dict:new()}.

handle_call({get, Key}, {Process, Tag}, Tables) ->
case dict:find(Key, Tables) of
{ok, Table} ->
true = ets:give_away(Table, Process, Tag), %% give away to calling process
{reply, {ok, Tag}, dict:erase(Key, Tables)};
error ->
{reply, {error, not_found}, Tables}
end;

handle_call(_Request, _From, State) ->
{noreply, State}.

handle_cast(_Msg, State) ->
{noreply, State}.

handle_info({'ETS-TRANSFER', Table, _, Key}, Tables) -> % retrieve table from died process
{noreply, dict:store(Key, Table, Tables)};

handle_info(_Info, State) ->
{noreply, State}.

terminate(_Reason, _State) ->
ok.

code_change(_OldVsn, State, _Extra) ->
{ok, State}.

%% like ets:new/2
new(Name, Options) when is_list(Name), is_list(Options) ->
new(list_to_atom(Name), Options);

new(Name, Options) when is_atom(Name), is_list(Options) ->
Key = {Name, Options},
Server = whereis(?MODULE), %% find yourself
case gen_server:call(Server, {get, Key}) of
{ok, Tag} -> %% we have such table
receive %% and give it back
{'ETS-TRANSFER', Table, Server, Tag} -> Table
after
?TIMEOUT -> %% shit happens
create({Name, Key}, Options, Server)
end;
{error, not_found} -> create({Name, Key}, Options, Server)
end.

create({Name, Key}, Options, Server) ->
O = case lists:keymember(heir, 1, Options) of
true -> Options; %% setup heir option if need
false -> [{heir, Server, Key} | Options]
end,
ets:new(Name, O).

0 comments on commit d9707b1

Please sign in to comment.