aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorAnders Svensson <[email protected]>2017-07-29 17:24:30 +0200
committerAnders Svensson <[email protected]>2017-08-03 17:17:37 +0200
commitbacca97210d31865c46b759115039b22f9ba9ed7 (patch)
tree12eab4fdb6c789e3fb8e294e344d64ca933a21f6 /lib
parent1a2c87f0035849fc5a24bff5dd36796500d1f451 (diff)
downloadotp-bacca97210d31865c46b759115039b22f9ba9ed7.tar.gz
otp-bacca97210d31865c46b759115039b22f9ba9ed7.tar.bz2
otp-bacca97210d31865c46b759115039b22f9ba9ed7.zip
Optimize sub-binaries
Also inline incr/8 and associated functions that were needed for the compiler to accept the optimization, since this does make for a measuable improvement.
Diffstat (limited to 'lib')
-rw-r--r--lib/diameter/src/base/diameter_gen.erl82
1 files changed, 56 insertions, 26 deletions
diff --git a/lib/diameter/src/base/diameter_gen.erl b/lib/diameter/src/base/diameter_gen.erl
index f0196ccaa9..7a1a46ec52 100644
--- a/lib/diameter/src/base/diameter_gen.erl
+++ b/lib/diameter/src/base/diameter_gen.erl
@@ -26,6 +26,14 @@
-module(diameter_gen).
+-compile({inline, [incr/8,
+ incr/4,
+ field/1,
+ setopts/4,
+ avp_arity/5,
+ set_failed/2,
+ set_strict/3]}).
+
-export([encode_avps/3,
decode_avps/3,
grouped_avp/4,
@@ -248,54 +256,76 @@ decode(<<Code:32, V:1, M:1, P:1, _:5, Len:24, I:V/unit:32, Rest/binary>>,
Mod,
Fmt,
Strict,
- Opts0,
- AM0) ->
- Vid = if 1 == V -> I; true -> undefined end,
- MB = 1 == M,
- PB = 1 == P,
- NameT = Mod:avp_name(Code, Vid), %% {AvpName, Type} | 'AVP'
- DataLen = Len - 8 - 4*V, %% possibly negative, causing case match to fail
- Pad = (4 - (Len rem 4)) rem 4,
+ Opts,
+ AM) ->
+ decode(Rest,
+ Code,
+ if 1 == V -> I; true -> undefined end,
+ Len - 8 - 4*V, %% possibly negative, causing case match to fail
+ (4 - (Len rem 4)) rem 4,
+ 1 == M,
+ 1 == P,
+ Name,
+ Mod,
+ Fmt,
+ Strict,
+ Opts,
+ AM);
- Opts = setopts(NameT, Name, MB, Opts0),
- %% Not AvpName or else a failed Failed-AVP
- %% decode is packed into 'AVP'.
+decode(<<>>, Name, Mod, Fmt, Strict, _, AM) ->
+ [AM, [], [] | newrec(Fmt, Mod, Name, Strict)];
- AvpName = field(NameT),
- Arity = avp_arity(Name, AvpName, Mod, Opts, MB),
- {Idx, AM} = incr(AvpName, Arity, Strict, AM0), %% count
+decode(Bin, Name, Mod, Fmt, Strict, _, AM) ->
+ Avp = #diameter_avp{data = Bin},
+ [AM, [Avp], [{5014, Avp}] | newrec(Fmt, Mod, Name, Strict)].
+
+%% decode/13
- case Rest of
+decode(Bin, Code, Vid, DataLen, Pad, M, P, Name, Mod, Fmt, Strict, Opts0, AM0) ->
+ case Bin of
<<Data:DataLen/binary, _:Pad/binary, T/binary>> ->
+ {NameT, AvpName, Arity, {Idx, AM}}
+ = incr(Name, Code, Vid, M, Mod, Strict, Opts0, AM0),
+
+ Opts = setopts(NameT, Name, M, Opts0),
+ %% Not AvpName or else a failed Failed-AVP
+ %% decode is packed into 'AVP'.
+
Avp = #diameter_avp{code = Code,
vendor_id = Vid,
- is_mandatory = MB,
- need_encryption = PB,
+ is_mandatory = M,
+ need_encryption = P,
data = Data,
name = name(NameT),
type = type(NameT),
index = Idx},
+
Dec = decode(Data, Name, NameT, Mod, Opts, Avp), %% decode
Acc = decode(T, Name, Mod, Fmt, Strict, Opts, AM), %% recurse
acc(Acc, Dec, Name, AvpName, Arity, Strict, Mod, Opts);
_ ->
+ {NameT, _AvpName, _Arity, {Idx, AM}}
+ = incr(Name, Code, Vid, M, Mod, Strict, Opts0, AM0),
+
Avp = #diameter_avp{code = Code,
vendor_id = Vid,
- is_mandatory = MB,
- need_encryption = PB,
- data = Rest,
+ is_mandatory = M,
+ need_encryption = P,
+ data = Bin,
name = name(NameT),
type = type(NameT),
index = Idx},
+
[AM, [Avp], [{5014, Avp}] | newrec(Fmt, Mod, Name, Strict)]
- end;
+ end.
-decode(<<>>, Name, Mod, Fmt, Strict, _, AM) ->
- [AM, [], [] | newrec(Fmt, Mod, Name, Strict)];
+%% incr/8
-decode(Bin, Name, Mod, Fmt, Strict, _, AM) ->
- Avp = #diameter_avp{data = Bin},
- [AM, [Avp], [{5014, Avp}] | newrec(Fmt, Mod, Name, Strict)].
+incr(Name, Code, Vid, M, Mod, Strict, Opts, AM0) ->
+ NameT = Mod:avp_name(Code, Vid), %% {AvpName, Type} | 'AVP'
+ AvpName = field(NameT),
+ Arity = avp_arity(Name, AvpName, Mod, Opts, M),
+ {NameT, AvpName, Arity, incr(AvpName, Arity, Strict, AM0)}.
%% Data is a truncated header if command_code = undefined, otherwise
%% payload bytes. The former is padded to the length of a header if