diff options
| author | Ron Yorston <rmy@pobox.com> | 2024-07-30 10:28:29 +0100 |
|---|---|---|
| committer | Ron Yorston <rmy@pobox.com> | 2024-07-30 10:28:29 +0100 |
| commit | dde99c5ae2511f8509dae85ce33b22d554ce157c (patch) | |
| tree | 83dc4c25f647e4d93bf321a2c82b88f7c43fb897 | |
| parent | bb8f6b688a6a8c7ac66b5c656d2544f9167a1abe (diff) | |
| download | busybox-w32-dde99c5ae2511f8509dae85ce33b22d554ce157c.tar.gz busybox-w32-dde99c5ae2511f8509dae85ce33b22d554ce157c.tar.bz2 busybox-w32-dde99c5ae2511f8509dae85ce33b22d554ce157c.zip | |
ash: rewrite waitpid_child() to improve performance
After the previous commit there was still a slight disparity
between shell performance with and without background jobs.
Reduce this disparity by the following changes:
- Remove the pidlist array. The PID of the exiting process can be
obtained from its handle.
- Save the proclist array between calls. It will always grow to
support the required number of PIDs.
- Combine the loops to compute the required size of proclist and
to fill it. This saves a few bytes with no measurable impact
on performance.
Saves 8 bytes in a 32-bit build, adds 32 in 64-bit.
(GitHub issue #434)
| -rw-r--r-- | shell/ash.c | 51 |
1 files changed, 19 insertions, 32 deletions
diff --git a/shell/ash.c b/shell/ash.c index ba29e3ea0..340c7ce2f 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
| @@ -4925,50 +4925,37 @@ static pid_t | |||
| 4925 | waitpid_child(int *status, int wait_flags) | 4925 | waitpid_child(int *status, int wait_flags) |
| 4926 | { | 4926 | { |
| 4927 | struct job *jb; | 4927 | struct job *jb; |
| 4928 | struct procstat *ps; | ||
| 4929 | int pid_nr = 0; | 4928 | int pid_nr = 0; |
| 4930 | pid_t *pidlist; | 4929 | static HANDLE *proclist = NULL; |
| 4931 | HANDLE *proclist; | 4930 | static int pid_max = 0; |
| 4932 | pid_t pid = -1; | 4931 | pid_t pid = -1; |
| 4933 | DWORD win_status, idx; | 4932 | DWORD win_status, idx; |
| 4934 | int i; | 4933 | int i; |
| 4935 | 4934 | ||
| 4936 | for (jb = curjob; jb; jb = jb->prev_job) { | 4935 | for (jb = curjob; jb; jb = jb->prev_job) { |
| 4937 | if (jb->state != JOBDONE) | 4936 | if (jb->state != JOBDONE) { |
| 4938 | pid_nr += jb->nprocs; | 4937 | if (pid_nr + jb->nprocs > pid_max) { |
| 4939 | } | 4938 | pid_max = pid_nr + jb->nprocs; |
| 4940 | if (pid_nr == 0) | 4939 | proclist = ckrealloc(proclist, sizeof(*proclist) * pid_max); |
| 4941 | return -1; | 4940 | } |
| 4942 | |||
| 4943 | pidlist = ckmalloc(sizeof(*pidlist)*pid_nr); | ||
| 4944 | proclist = ckmalloc(sizeof(*proclist)*pid_nr); | ||
| 4945 | 4941 | ||
| 4946 | pid_nr = 0; | 4942 | for (i = 0; i < jb->nprocs; ++i) { |
| 4947 | for (jb = curjob; jb; jb = jb->prev_job) { | 4943 | if (jb->ps[i].ps_proc) { |
| 4948 | if (jb->state == JOBDONE) | 4944 | proclist[pid_nr++] = jb->ps[i].ps_proc; |
| 4949 | continue; | 4945 | } |
| 4950 | ps = jb->ps; | ||
| 4951 | for (i = 0; i < jb->nprocs; ++i) { | ||
| 4952 | if (ps[i].ps_proc) { | ||
| 4953 | pidlist[pid_nr] = ps[i].ps_pid; | ||
| 4954 | proclist[pid_nr++] = ps[i].ps_proc; | ||
| 4955 | } | 4946 | } |
| 4956 | } | 4947 | } |
| 4957 | } | 4948 | } |
| 4958 | 4949 | ||
| 4959 | if (pid_nr == 0) | 4950 | if (pid_nr) { |
| 4960 | goto done; | 4951 | idx = WaitForMultipleObjects(pid_nr, proclist, FALSE, |
| 4961 | 4952 | wait_flags & WNOHANG ? 0 : INFINITE); | |
| 4962 | idx = WaitForMultipleObjects(pid_nr, proclist, FALSE, | 4953 | if (idx < pid_nr) { |
| 4963 | wait_flags & WNOHANG ? 0 : INFINITE); | 4954 | GetExitCodeProcess(proclist[idx], &win_status); |
| 4964 | if (idx < pid_nr) { | 4955 | *status = exit_code_to_wait_status(win_status); |
| 4965 | GetExitCodeProcess(proclist[idx], &win_status); | 4956 | pid = GetProcessId(proclist[idx]); |
| 4966 | *status = exit_code_to_wait_status(win_status); | 4957 | } |
| 4967 | pid = pidlist[idx]; | ||
| 4968 | } | 4958 | } |
| 4969 | done: | ||
| 4970 | free(pidlist); | ||
| 4971 | free(proclist); | ||
| 4972 | return pid; | 4959 | return pid; |
| 4973 | } | 4960 | } |
| 4974 | #define waitpid(p, s, f) waitpid_child(s, f) | 4961 | #define waitpid(p, s, f) waitpid_child(s, f) |
