Просмотр исходного кода

Speed up `realpath()` with dynamically loaded C extension

On systems that support both C compiling and dynamic loading, we can
speed up `realpath()` (where most time in rbenv is spent) by replacing
it with a dynamically loaded bash builtin.

When `make -C src` is called in the project's root,
`libexec/rbenv-realpath.dylib` will be created. If it exists, rbenv will
attempt to load it as a builtin command. If it fails, execution will
fall back to the old `realpath()` shell function.
pull/360/head^2
Mislav Marohnić 12 лет назад
Родитель
Сommit
16c7eb4135
5 измененных файлов: 89 добавлений и 1 удалений
  1. +2
    -0
      .gitignore
  2. +3
    -1
      libexec/rbenv-hooks
  3. +10
    -0
      src/Makefile
  4. +31
    -0
      src/bash.h
  5. +43
    -0
      src/realpath.c

+ 2
- 0
.gitignore Просмотреть файл

@ -4,3 +4,5 @@
/versions
/sources
/cache
/libexec/*.dylib
/src/*.o

+ 3
- 1
libexec/rbenv-hooks Просмотреть файл

@ -19,6 +19,7 @@ if [ -z "$RBENV_COMMAND" ]; then
exit 1
fi
if ! enable -f "${BASH_SOURCE%/*}"/rbenv-realpath.dylib realpath 2>/dev/null; then
READLINK=$(type -p greadlink readlink | head -1)
if [ -z "$READLINK" ]; then
echo "rbenv: cannot find readlink - are you missing GNU coreutils?" >&2
@ -42,13 +43,14 @@ realpath() {
echo "$(pwd)/$name"
cd "$cwd"
}
fi
IFS=: hook_paths=($RBENV_HOOK_PATH)
shopt -s nullglob
for path in "${hook_paths[@]}"; do
for script in "$path/$RBENV_COMMAND"/*.bash; do
echo $(realpath $script)
realpath "$script"
done
done
shopt -u nullglob

+ 10
- 0
src/Makefile Просмотреть файл

@ -0,0 +1,10 @@
SHOBJ_LDFLAGS = -dynamiclib -current_version 1.0
.c.o:
$(CC) $(CFLAGS) -c -o $@ $<
../libexec/rbenv-realpath.dylib: realpath.o
$(CC) $(CFLAGS) $(SHOBJ_LDFLAGS) -o $@ realpath.o
clean:
rm -f *.o ../libexec/*.dylib

+ 31
- 0
src/bash.h Просмотреть файл

@ -0,0 +1,31 @@
#ifndef __BASH_H__
#define __BASH_H__
#define EXECUTION_SUCCESS 0
#define EXECUTION_FAILURE 1
#define EX_USAGE 258
#define BUILTIN_ENABLED 1
typedef struct word_desc {
char *word;
int flags;
} WORD_DESC;
typedef struct word_list {
struct word_list *next;
WORD_DESC *word;
} WORD_LIST;
typedef int sh_builtin_func_t(WORD_LIST *);
struct builtin {
char *name;
sh_builtin_func_t *function;
int flags;
char * const *long_doc;
const char *short_doc;
char *unused;
};
#endif

+ 43
- 0
src/realpath.c Просмотреть файл

@ -0,0 +1,43 @@
#include "bash.h"
#include <stdlib.h>
#include <stdio.h>
int realpath_builtin(list)
WORD_LIST *list;
{
int es;
char *realbuf, *p;
if (list == 0) {
// builtin_usage();
return (EX_USAGE);
}
for (es = EXECUTION_SUCCESS; list; list = list->next) {
p = list->word->word;
realbuf = realpath(p, NULL);
if (realbuf == NULL) {
es = EXECUTION_FAILURE;
// builtin_error("%s: cannot resolve: %s", p, strerror(errno));
} else {
printf("%s\n", realbuf);
free(realbuf);
}
}
return es;
}
char *realpath_doc[] = {
"Display each PATHNAME argument, resolving symbolic links. The exit status",
"is 0 if each PATHNAME was resolved; non-zero otherwise.",
(char *)NULL
};
struct builtin realpath_struct = {
"realpath",
realpath_builtin,
BUILTIN_ENABLED,
realpath_doc,
"realpath pathname [pathname...]",
0
};

Загрузка…
Отмена
Сохранить