sched/environ: Improve performance of set/unset environment

reserve dimensional array of environment to avoid frequent scaling

Signed-off-by: chao an <anchao@lixiang.com>
This commit is contained in:
chao an 2024-03-27 10:41:15 +08:00 committed by Xiang Xiao
parent 446e0280b0
commit ad4fb55d1f
6 changed files with 47 additions and 30 deletions

View File

@ -507,6 +507,7 @@ struct task_group_s
/* Environment variables **************************************************/
FAR char **tg_envp; /* Allocated environment strings */
ssize_t tg_envpc; /* Maximum entries of environment array */
ssize_t tg_envc; /* Number of environment strings */
#endif

View File

@ -88,6 +88,7 @@ int env_dup(FAR struct task_group_s *group, FAR char * const *envcp)
}
group->tg_envc = envc;
group->tg_envpc = (envc + SCHED_ENVIRON_RESERVED + 1);
/* A special case is that the parent has an "empty" environment
* allocation, i.e., there is an allocation in place but it
@ -98,7 +99,7 @@ int env_dup(FAR struct task_group_s *group, FAR char * const *envcp)
{
/* There is an environment, duplicate it */
envp = group_malloc(group, sizeof(*envp) * (envc + 1));
envp = group_malloc(group, sizeof(*envp) * group->tg_envpc);
if (envp == NULL)
{
/* The parent's environment can not be inherited due to a

View File

@ -83,8 +83,9 @@ void env_release(FAR struct task_group_s *group)
* task group structure are reset to initial values.
*/
group->tg_envp = NULL;
group->tg_envc = 0;
group->tg_envp = NULL;
group->tg_envpc = 0;
group->tg_envc = 0;
}
#endif /* CONFIG_DISABLE_ENVIRON */

View File

@ -86,14 +86,17 @@ void env_removevar(FAR struct task_group_s *group, ssize_t index)
{
group_free(group, group->tg_envp);
group->tg_envp = NULL;
group->tg_envpc = 0;
}
else
else if (group->tg_envc <=
(group->tg_envpc - SCHED_ENVIRON_RESERVED * 2))
{
/* Reallocate the environment to reclaim a little memory */
group->tg_envpc = group->tg_envc + SCHED_ENVIRON_RESERVED + 1;
group->tg_envp = group_realloc(group, group->tg_envp,
sizeof(*group->tg_envp) *
(group->tg_envc + 1));
sizeof(*group->tg_envp) * group->tg_envpc);
DEBUGASSERT(group->tg_envp != NULL);
}
}

View File

@ -71,7 +71,8 @@ int setenv(FAR const char *name, FAR const char *value, int overwrite)
FAR struct task_group_s *group;
FAR char *pvar;
FAR char **envp;
ssize_t envc = 0;
ssize_t envc;
ssize_t envpc;
ssize_t ret = OK;
int varlen;
@ -153,33 +154,41 @@ int setenv(FAR const char *name, FAR const char *value, int overwrite)
goto errout_with_lock;
}
if (group->tg_envp)
{
envc = group->tg_envc;
envp = group_realloc(group, group->tg_envp,
sizeof(*envp) * (envc + 2));
if (envp == NULL)
{
ret = ENOMEM;
goto errout_with_var;
}
}
else
{
envp = group_malloc(group, sizeof(*envp) * 2);
if (envp == NULL)
{
ret = ENOMEM;
goto errout_with_var;
}
}
envc = group->tg_envc;
envp[envc++] = pvar;
envp[envc] = NULL;
if (group->tg_envp == NULL)
{
envpc = SCHED_ENVIRON_RESERVED + 2;
envp = group_malloc(group, sizeof(*envp) * envpc);
if (envp == NULL)
{
ret = ENOMEM;
goto errout_with_var;
}
group->tg_envp = envp;
group->tg_envpc = envpc;
}
else if (envc >= group->tg_envpc - 1)
{
envpc = envc + SCHED_ENVIRON_RESERVED + 2;
envp = group_realloc(group, group->tg_envp, sizeof(*envp) * envpc);
if (envp == NULL)
{
ret = ENOMEM;
goto errout_with_var;
}
group->tg_envp = envp;
group->tg_envpc = envpc;
}
/* Save the new buffer and count */
group->tg_envp = envp;
group->tg_envp[envc++] = pvar;
group->tg_envp[envc] = NULL;
group->tg_envc = envc;
/* Now, put the new name=value string into the environment buffer */

View File

@ -37,6 +37,8 @@
# define env_release(group) (0)
#else
# define SCHED_ENVIRON_RESERVED (4)
/****************************************************************************
* Public Data
****************************************************************************/