On systems where we pull in around 100k users from ldap, ypldap uses a
fair bit of memory (over 300MB peak) moving data from the ldapclient process
to the main process.

The ldapclient process sends each user and group record to the parent process
in instances of struct idm_req, which includes a 1kB buffer for the user/group
details.  It currently sends the full struct through imsg, but only sending
the used portion of the 1kB buffer reduces peak memory usage to around 100MB,
and it turns out it's pretty easy, as in the diff below.

ok?


Index: ldapclient.c
===================================================================
RCS file: /cvs/src/usr.sbin/ypldap/ldapclient.c,v
retrieving revision 1.46
diff -u -p -r1.46 ldapclient.c
--- ldapclient.c        13 Oct 2022 04:55:33 -0000      1.46
+++ ldapclient.c        27 Mar 2023 04:19:53 -0000
@@ -567,7 +567,8 @@ client_search_idm(struct env *env, struc
 
                        if (client_build_req(idm, &ir, m, min_attr, max_attr) 
== 0)
                                imsg_compose_event(env->sc_iev, type, 0, 0, -1,
-                                   &ir, sizeof(ir));
+                                   &ir, sizeof(ir.ir_key) +
+                                   strlen(ir.ir_line) + 1);
 
                        aldap_freemsg(m);       
                }
Index: ypldap.c
===================================================================
RCS file: /cvs/src/usr.sbin/ypldap/ypldap.c,v
retrieving revision 1.23
diff -u -p -r1.23 ypldap.c
--- ypldap.c    22 Aug 2022 08:02:02 -0000      1.23
+++ ypldap.c    27 Mar 2023 04:19:53 -0000
@@ -392,7 +392,7 @@ main_dispatch_client(int fd, short event
                        if (env->update_trashed)
                                break;
 
-                       (void)memcpy(&ir, imsg.data, sizeof(ir));
+                       (void)memcpy(&ir, imsg.data, n - IMSG_HEADER_SIZE);
                        if ((ue = calloc(1, sizeof(*ue))) == NULL ||
                            (ue->ue_line = strdup(ir.ir_line)) == NULL) {
                                /*
@@ -418,7 +418,7 @@ main_dispatch_client(int fd, short event
                        if (env->update_trashed)
                                break;
 
-                       (void)memcpy(&ir, imsg.data, sizeof(ir));
+                       (void)memcpy(&ir, imsg.data, n - IMSG_HEADER_SIZE);
                        if ((ge = calloc(1, sizeof(*ge))) == NULL ||
                            (ge->ge_line = strdup(ir.ir_line)) == NULL) {
                                /*

Reply via email to