aboutsummaryrefslogtreecommitdiffstats
path: root/lib/stdlib/src/zip.erl
diff options
context:
space:
mode:
authorDan Gudmundsson <[email protected]>2015-08-21 13:13:17 +0200
committerDan Gudmundsson <[email protected]>2015-08-24 11:45:20 +0200
commit02abeffc9d753b5fcd1ce7da93f437887f574bad (patch)
tree8e100be76c908a98219dedd321e6e4eac26c7e3e /lib/stdlib/src/zip.erl
parente0aad557854cf7d24ead9db62d4aaa1927b221c7 (diff)
downloadotp-02abeffc9d753b5fcd1ce7da93f437887f574bad.tar.gz
otp-02abeffc9d753b5fcd1ce7da93f437887f574bad.tar.bz2
otp-02abeffc9d753b5fcd1ce7da93f437887f574bad.zip
Optimize zip:unzip/2 when uncompressing to memory
Optimize the case where we are appending to the end of the binary, use binary syntax to create binaries with room for expansion in the next loop, instead of using iolist_to_binary which creates a binary of the exact size and needs to be copied in each loop. Also remove support the unused Acc as iolists.
Diffstat (limited to 'lib/stdlib/src/zip.erl')
-rw-r--r--lib/stdlib/src/zip.erl68
1 files changed, 22 insertions, 46 deletions
diff --git a/lib/stdlib/src/zip.erl b/lib/stdlib/src/zip.erl
index d6031dabbc..bec0bd3f6d 100644
--- a/lib/stdlib/src/zip.erl
+++ b/lib/stdlib/src/zip.erl
@@ -1550,57 +1550,33 @@ unix_extra_field_and_var_from_bin(_) ->
%% A pwrite-like function for iolists (used by memory-option)
-split_iolist(B, Pos) when is_binary(B) ->
- split_binary(B, Pos);
-split_iolist(L, Pos) when is_list(L) ->
- splitter([], L, Pos).
-
-splitter(Left, Right, 0) ->
- {Left, Right};
-splitter(Left, [A | Right], RelPos) when is_list(A) or is_binary(A) ->
- Sz = erlang:iolist_size(A),
- case Sz > RelPos of
- true ->
- {Leftx, Rightx} = split_iolist(A, RelPos),
- {[Left | Leftx], [Rightx, Right]};
- _ ->
- splitter([Left | A], Right, RelPos - Sz)
- end;
-splitter(Left, [A | Right], RelPos) when is_integer(A) ->
- splitter([Left, A], Right, RelPos - 1);
-splitter(Left, Right, RelPos) when is_binary(Right) ->
- splitter(Left, [Right], RelPos).
+pwrite_binary(B, Pos, Bin) when byte_size(B) =:= Pos ->
+ append_bins(Bin, B);
+pwrite_binary(B, Pos, Bin) ->
+ erlang:iolist_to_binary(pwrite_iolist(B, Pos, Bin)).
-skip_iolist(B, Pos) when is_binary(B) ->
- case B of
- <<_:Pos/binary, Bin/binary>> -> Bin;
- _ -> <<>>
- end;
-skip_iolist(L, Pos) when is_list(L) ->
- skipper(L, Pos).
-
-skipper(Right, 0) ->
- Right;
-skipper([A | Right], RelPos) when is_list(A) or is_binary(A) ->
- Sz = erlang:iolist_size(A),
- case Sz > RelPos of
- true ->
- Rightx = skip_iolist(A, RelPos),
- [Rightx, Right];
- _ ->
- skip_iolist(Right, RelPos - Sz)
- end;
-skipper([A | Right], RelPos) when is_integer(A) ->
- skip_iolist(Right, RelPos - 1).
+append_bins([Bin|Bins], B) when is_binary(Bin) ->
+ append_bins(Bins, <<B/binary, Bin/binary>>);
+append_bins([List|Bins], B) when is_list(List) ->
+ append_bins(Bins, append_bins(List, B));
+append_bins(Bin, B) when is_binary(Bin) ->
+ <<B/binary, Bin/binary>>;
+append_bins([_|_]=List, B) ->
+ <<B/binary, (iolist_to_binary(List))/binary>>;
+append_bins([], B) ->
+ B.
-pwrite_iolist(Iolist, Pos, Bin) ->
- {Left, Right} = split_iolist(Iolist, Pos),
+pwrite_iolist(B, Pos, Bin) ->
+ {Left, Right} = split_binary(B, Pos),
Sz = erlang:iolist_size(Bin),
- R = skip_iolist(Right, Sz),
+ R = skip_bin(Right, Sz),
[Left, Bin | R].
-pwrite_binary(B, Pos, Bin) ->
- erlang:iolist_to_binary(pwrite_iolist(B, Pos, Bin)).
+skip_bin(B, Pos) when is_binary(B) ->
+ case B of
+ <<_:Pos/binary, Bin/binary>> -> Bin;
+ _ -> <<>>
+ end.
%% ZIP header manipulations