File 0579-Optimize-pkix_db-cert-selection.patch of Package erlang
From bc35b4f14f100bf95db685d704f06d076bfb8c31 Mon Sep 17 00:00:00 2001
From: John Altenmueller <jaltenmueller@whatsapp.com>
Date: Thu, 30 Nov 2023 16:32:19 -0800
Subject: [PATCH] Optimize pkix_db cert selection
During high load, we observe lock contention on this ETS table:
```
> lcnt:inspect(db_tab, [{print, [id, colls, ratio, duration]}]).
id #collisions collisions [%] duration [%]
--- ------------ --------------- -------------
ssl_otp_cacertificate_db 7827 12.5136 616.1264
ssl_otp_ca_file_ref 30 0.2561 0.0026
```
ets:select is more efficient than using ets:foldl and in practice
reduces the contention that we see here.
Separately I plan to also issue another PR to add read_concurrency to
the ETS table which has also helped reduce the incidence of this.
---
lib/ssl/src/ssl_handshake.erl | 7 +------
lib/ssl/src/ssl_pkix_db.erl | 10 +++++++++-
2 files changed, 10 insertions(+), 7 deletions(-)
diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl
index d44ed05e85..05a084a9f2 100644
--- a/lib/ssl/src/ssl_handshake.erl
+++ b/lib/ssl/src/ssl_handshake.erl
@@ -2019,12 +2019,7 @@ supported_cert_type_or_empty(Algo, Type) ->
end.
certificate_authorities_from_db(CertDbHandle, CertDbRef) when is_reference(CertDbRef) ->
- ConnectionCerts = fun({{Ref, _, _}, Cert}, Acc) when Ref == CertDbRef ->
- [Cert | Acc];
- (_, Acc) ->
- Acc
- end,
- ssl_pkix_db:foldl(ConnectionCerts, [], CertDbHandle);
+ ssl_pkix_db:select_certs_by_ref(CertDbRef, CertDbHandle);
certificate_authorities_from_db(_CertDbHandle, {extracted, CertDbData}) ->
%% Cache disabled, Ref contains data
lists:foldl(fun({decoded, {_Key,Cert}}, Acc) -> [Cert | Acc] end,
diff --git a/lib/ssl/src/ssl_pkix_db.erl b/lib/ssl/src/ssl_pkix_db.erl
index eac9e2a8b3..4932f923c3 100644
--- a/lib/ssl/src/ssl_pkix_db.erl
+++ b/lib/ssl/src/ssl_pkix_db.erl
@@ -36,7 +36,7 @@
extract_trusted_certs/1,
remove_trusted_certs/2, insert/3, remove/2, clear/1, db_size/1,
ref_count/3, lookup_trusted_cert/4, foldl/3, select_certentries_by_ref/2,
- decode_pem_file/1, lookup/2]).
+ select_certs_by_ref/2, decode_pem_file/1, lookup/2]).
%%====================================================================
%% Internal application API
@@ -251,6 +251,14 @@ foldl(Fun, Acc0, Cache) ->
select_certentries_by_ref(Ref, Cache) ->
ets:select(Cache, [{{{Ref,'_', '_'}, '_'},[],['$_']}]).
+%%--------------------------------------------------------------------
+-spec select_certs_by_ref(reference(), db_handle()) -> term().
+%%
+%% Description: Select certs originating from same source
+%%--------------------------------------------------------------------
+select_certs_by_ref(Ref, Cache) ->
+ ets:select(Cache, [{{{Ref,'_','_'},'$1'},[],['$1']}]).
+
%%--------------------------------------------------------------------
-spec ref_count(term(), db_handle(), integer()) -> integer().
%%
--
2.35.3