A silly non-performant array implementation on top of ets.
For "benchmarks" scroll all the way down.
I "needed" an array/stack with Javascript-like semantics: ability to push, pop, randomly access and update elements, slice and splice.
A 2-D dynamically growing array implemented on top of a set
table in ets.
Unless a Row
parameter is specified, all functions by default operate on
Row 0. In other words: if you do not specify a Row
, your array will behave
as an array with one row only.
If something crashes, your data is gone, as nothing is done to protect the ets table (yet?).
If several processes access the dictionary, strange things will happen (once again: ets).
Note: all API calls that accept From, Count
also accept a negative From
.
If From < 0
, starting element will be counted from the end of the array.
new()
: get a random handle to a new arraynew(Handle::atom())
: get a new array with your own handleteardown(Handle)
: delete the array
length(Handle)
: lengthlength(Handle, Row)
: length of row
push(Handle, Item)
: push. Equivalent toinsert_at(Handle, 0, Item)
push(Handle, Row, Item)
: push to row. Equivalent toinsert_at(Handle, Row, 0, Item)
pop(Handle)
: pop. Equivalent toat(Handle, 0)
pop(Handle, Row)
: pop from row. Equivalent toat(Handle, Row, 0)
pop_n(Handle, N)
: pop N items. Equivalent tosplice(Handle, 0, N)
pop_n(Handle, Row, N)
: pop N items from Row. Equivalent tosplice(Handle, Row, 0, N)
slice(Handle, From, Count)
: Only leave the items betweenFrom
andFrom + Count
in the stackslice(Handle, Row, From, Count)
: Same for a rowsplice(Handle, From, Count)
: Remove and return items betweenFrom
andFrom + Count
in the stacksplice(Handle, Row, From, Count)
: Same for a rowinsert_at(Handle, Index, Item)
: InsertItem
atIndex
insert_at(Handle, Row, Index, Item)
: InsertItem
atIndex
inRow
update_at(Handle, Index, Item)
: UpdateItem
atIndex
update_at(Handle, Row, Index, Item)
: UpdateItem
atIndex
inRow
empty(Handle)
: Empty the entire array (remove all items from all rows)
range(Handle, From, Count)
: Return items betweenFrom
andFrom + Count
. Leave array intactrange(Handle, Row, From, Count)
: Same for a rowat(Handle, Index)
: Alias fornth
at(Handle, Row, Index)
: Alias fornth
nth(Handle, Index)
: ReturnItem
atIndex
. Leave array intact.nth(Handle, Row, Index)
: ReturnItem
atIndex
atRow
. Leave array intact.
Non-scientific ballpark figures using a Macbook Pro and statistics/1
.
> F = fun(Fun) ->
statistics(runtime),
statistics(wall_clock),
Fun(),
{_, Time1} = statistics(runtime),
{_, Time2} = statistics(wall_clock),
U1 = Time1,
U2 = Time2,
io:format("Code time=~p (~p) milliseconds~n", [U1,U2])
end.
> L = lists:seq(0, 10000).
> %% Create new
> F(fun() -> arrets:new(test) end).
Code time=0 (0) milliseconds
> %% Push 10 000 items
> F(fun() -> lists:foreach(fun(E) -> arrets:push(test, E) end, L) end).
Code time=2530 (2564) milliseconds
> %% Pop those back. It's slower due rather inneficient code governing this
> %% But don't fret, it's not too bad. See times for splice/range/at below
> F(fun() -> lists:foreach(fun(_) -> arrets:pop(test) end, L) end).
Code time=8430 (8511) milliseconds
> %% Repopulate
> lists:foreach(fun(E) -> arrets:push(test, E) end, L).
> %% Get back a random range
> F(fun() -> arrets:range(test, 1337, 1337) end).
Code time=0 (3) milliseconds
> %% Remove a random range
> F(fun() -> arrets:splice(test, 1337, 1337) end).
Code time=10 (10) milliseconds
> %% Leave a random range
> F(fun() -> arrets:slice(test, 1337, 1337) end).
Code time=0 (5) milliseconds
> %% Empty and repopulate
> arrets:empty(test), lists:foreach(fun(E) -> arrets:push(test, E) end, L).
> %% Access a random element
> F(fun() -> arrets:at(test, 1337) end).
Code time=0 (1) milliseconds
> %% Pop n elements
> F(fun() -> arrets:pop_n(test, 1337) end).
Code time=10 (8) milliseconds
> %% Empty array
> F(fun() -> arrets:empty(test) end).
Code time=0 (1) milliseconds
> %% Destroy array
> F(fun() -> arrets:teardown(test) end).
Code time=0 (0) milliseconds