[erlang-questions] per function/process locals
Ulf Wiger
ulf@REDACTED
Thu May 10 13:42:20 CEST 2007
2007/5/3, ok <ok@REDACTED>:
>
> On 2 May 2007, at 11:21 pm, Ulf Wiger (TN/EAB) wrote
> [that instead of doing]
> > init_state(L) ->
> > lists:foldl(
> > fun({a, A}, S) -> S#st{a = A};
> > ({b, B}, S) -> S#st{b = B};
> > ...
> > end, #st{}, L).
> [he tends to do]
> > [A, B, C, D] =
> > [proplists:get_value(K,L) ||
> > K <- [a, b, c, d]],
> > #st{a = A, b = B, c = C, d = D}
>
> This is a rather interesting example, because it shows a clear trade-
> off.
> Suppose there are V "variables". We expect that the list will contain
> each at most once; the worst case is when they all appear.
Just to give some concrete input, we are currently looking at how to
best populate a fairly large record, consisting of 42 attributes.
I'm thinking that the exprecs contrib (that I've posted in the trapexit
User Contributions forum) could try to output code that gives a reasonable
tradeoff based on size of record and (possibly) length of list.
Currently, it lays out the following code:
-record(dia_base_DPR,
{'Origin-Host' = undefined, 'Origin-Realm' = undefined,
'Disconnect-Cause' = undefined}).
'#set-dia_base_DPR'(Vals, Rec) ->
F = fun ([], R, _F1) -> R;
([{'Origin-Host', V} | T], R, F1) ->
F1(T, R#dia_base_DPR{'Origin-Host' = V}, F1);
([{'Origin-Realm', V} | T], R, F1) ->
F1(T, R#dia_base_DPR{'Origin-Realm' = V}, F1);
([{'Disconnect-Cause', V} | T], R, F1) ->
F1(T, R#dia_base_DPR{'Disconnect-Cause' = V}, F1)
end,
F(Vals, Rec, F).
... but for a record of size 44, this is not desirable.
Timing the two functions available for creating a new record:
-module(test4).
-compile(export_all).
-compile({parse_transform, exprecs}).
-export_records([r]).
-record(r, {a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,
a11,a12,a13,a14,a15,a16,a17,a18,
a19,a20,a21,a22,a23,a24,a25,a26,
a27,a28,a29,a30,a31,a32,a33,a34,
a35,a36,a37,a38,a39,a40,a41,a42,
a43,a44,a45,a46,a47,a48,a49,a50}).
3> timer:tc(test4,'#new-r',[]).
{5, {r,undefined,...}}
4> Attrs = test4:'#info-r'(fields).
[a1, a2, a3, a4,...]
5> Vals = [{A,1} || A <- Attrs].
[{a1,1}, {a2,1}, {a3,1}, {a4,1},...]
6> timer:tc(test4,'#new-r',[Vals]).
{98,{r,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,...}}
I wrote a version basically doing this:
-module(recgen).
-export(['#new-r'/1]).
'#new-r'(L) ->
mk_rec(L, undefined, undefined).
mk_rec([{Attr,Val}|T], X1, X2) ->
X1 = if Attr == a1 -> Val; true -> X1 end,
X2 = if Attr == a2 -> Val; true -> X2 end,
mk_rec(T, X1, X2);
mk_rec([], X1, X2) ->
'#new-r'(X1, X2).
'#new-r'(X1, X2) ->
{r,X1,X2}.
...but for a record with 50 attributes, this was twice as slow
when setting all 50 attributes. Obviously, wielding functions
of arity 51 is not for free. (:
BR,
Ulf W
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://erlang.org/pipermail/erlang-questions/attachments/20070510/a0d9c464/attachment.htm>
More information about the erlang-questions
mailing list