File 5632-Use-ets-whereis-in-ets-fold.patch of Package erlang
From c05f35c0e25011bf1e5d4d63e921e9cde9203e72 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Micha=C5=82=20Muska=C5=82a?= <micmus@fb.com>
Date: Mon, 12 Feb 2024 11:45:32 +0000
Subject: [PATCH 2/2] Use ets:whereis in ets:fold*
Accessing the table by ref is significantly faster than by name. We know we'll
be accessing the table multiple times in a loop - it's worth it resolving the
name just once before starting the operation.
---
lib/stdlib/src/ets.erl | 13 +++++++++++--
lib/stdlib/test/ets_SUITE.erl | 11 +++++++++--
2 files changed, 20 insertions(+), 4 deletions(-)
diff --git a/lib/stdlib/src/ets.erl b/lib/stdlib/src/ets.erl
index 3716c5bfa2..54d687d21b 100644
--- a/lib/stdlib/src/ets.erl
+++ b/lib/stdlib/src/ets.erl
@@ -688,7 +688,8 @@ the traversal.
AccIn :: term(),
AccOut :: term().
-foldl(F, Accu, T) ->
+foldl(F, Accu, Tab) ->
+ T = soft_whereis(Tab),
ets:safe_fixtable(T, true),
First = ets:first_lookup(T),
try
@@ -710,7 +711,8 @@ the traversal.
AccIn :: term(),
AccOut :: term().
-foldr(F, Accu, T) ->
+foldr(F, Accu, Tab) ->
+ T = soft_whereis(Tab),
ets:safe_fixtable(T, true),
Last = ets:last_lookup(T),
try
@@ -724,6 +726,13 @@ do_foldr(F, Accu0, {Key, Objects}, T) ->
Accu = lists:foldr(F, Accu0, Objects),
do_foldr(F, Accu, ets:prev_lookup(T, Key), T).
+soft_whereis(Table) when is_atom(Table) ->
+ case ets:whereis(Table) of
+ undefined -> error(badarg, [Table], [{error_info, #{cause => id, module => erl_stdlib_errors}}]);
+ Ref -> Ref
+ end;
+soft_whereis(Table) -> Table.
+
-spec from_dets(Table, DetsTab) -> 'true' when
Table :: table(),
DetsTab :: dets:tab_name().
diff --git a/lib/stdlib/test/ets_SUITE.erl b/lib/stdlib/test/ets_SUITE.erl
index 2aa692bea7..a9b83debe0 100644
--- a/lib/stdlib/test/ets_SUITE.erl
+++ b/lib/stdlib/test/ets_SUITE.erl
@@ -42,7 +42,8 @@
tabfile_ext2/1, tabfile_ext3/1, tabfile_ext4/1, badfile/1]).
-export([heavy_lookup/1, heavy_lookup_element/1, heavy_concurrent/1]).
-export([lookup_element_mult/1, lookup_element_default/1]).
--export([foldl_ordered/1, foldr_ordered/1, foldl/1, foldr/1, fold_empty/1]).
+-export([foldl_ordered/1, foldr_ordered/1, foldl/1, foldr/1, fold_empty/1,
+ fold_badarg/1]).
-export([t_delete_object/1, t_init_table/1, t_whitebox/1,
select_bound_chunk/1, t_delete_all_objects/1, t_test_ms/1,
t_delete_all_objects_trap/1,
@@ -118,6 +119,7 @@
-export([t_select_reverse/1]).
-include_lib("stdlib/include/ms_transform.hrl"). % ets:fun2ms
+-include_lib("stdlib/include/assert.hrl").
-include_lib("common_test/include/ct.hrl").
-include_lib("common_test/include/ct_event.hrl").
@@ -219,7 +221,7 @@ groups() ->
[heavy_lookup, heavy_lookup_element, heavy_concurrent]},
{fold, [],
[foldl_ordered, foldr_ordered, foldl, foldr,
- fold_empty]},
+ fold_empty, fold_badarg]},
{meta_smp, [],
[meta_lookup_unnamed_read, meta_lookup_unnamed_write,
meta_lookup_named_read, meta_lookup_named_write,
@@ -6427,6 +6429,11 @@ fold_empty(Config) when is_list(Config) ->
end),
ok.
+fold_badarg(Config) when is_list(Config) ->
+ F = fun(_, _) -> ok end,
+ ?assertError(badarg, ets:foldl(F, [], non_existing)),
+ ?assertError(badarg, ets:foldr(F, [], non_existing)).
+
foldl(Config) when is_list(Config) ->
repeat_for_opts_all_table_types(
fun(Opts) ->
--
2.35.3