# HG changeset patch # User Bryan O'Sullivan # Date 1354567224 28800 # Node ID ddc0323db78b45f4f6459e9bc29f3a86f1ed8352 # Parent 9b05b31b413c55d750ca8be41330ff65fa9ed8c1 osutil: write a C implementation of statfiles for unix This makes a big difference to performance. In a clean working directory containing 170,000 files, performance of "hg --time diff" improves from 2.38 seconds to 1.69. diff -r 9b05b31b413c -r ddc0323db78b mercurial/osutil.c --- a/mercurial/osutil.c Fri Nov 30 17:40:11 2012 -0800 +++ b/mercurial/osutil.c Mon Dec 03 12:40:24 2012 -0800 @@ -389,6 +389,55 @@ return ret; } +static PyObject *statfiles(PyObject *self, PyObject *args) +{ + PyObject *names, *stats; + Py_ssize_t i, count; + + if (!PyArg_ParseTuple(args, "O:statfiles", &names)) + return NULL; + + count = PySequence_Length(names); + if (count == -1) { + PyErr_SetString(PyExc_TypeError, "not a sequence"); + return NULL; + } + + stats = PyList_New(count); + if (stats == NULL) + return NULL; + + for (i = 0; i < count; i++) { + PyObject *stat; + struct stat st; + int ret, kind; + char *path; + + path = PyString_AsString(PySequence_GetItem(names, i)); + if (path == NULL) { + PyErr_SetString(PyExc_TypeError, "not a string"); + goto bail; + } + ret = lstat(path, &st); + kind = st.st_mode & S_IFMT; + if (ret != -1 && (kind == S_IFREG || kind == S_IFLNK)) { + stat = makestat(&st); + if (stat == NULL) + goto bail; + PyList_SET_ITEM(stats, i, stat); + } else { + Py_INCREF(Py_None); + PyList_SET_ITEM(stats, i, Py_None); + } + } + + return stats; + +bail: + Py_DECREF(stats); + return NULL; +} + #endif /* ndef _WIN32 */ static PyObject *listdir(PyObject *self, PyObject *args, PyObject *kwargs) @@ -553,6 +602,10 @@ {"posixfile", (PyCFunction)posixfile, METH_VARARGS | METH_KEYWORDS, "Open a file with POSIX-like semantics.\n" "On error, this function may raise either a WindowsError or an IOError."}, +#else + {"statfiles", (PyCFunction)statfiles, METH_VARARGS | METH_KEYWORDS, + "stat a series of files or symlinks\n" +"Returns None for non-existent entries and entries of other types.\n"}, #endif #ifdef __APPLE__ { diff -r 9b05b31b413c -r ddc0323db78b mercurial/util.py --- a/mercurial/util.py Fri Nov 30 17:40:11 2012 -0800 +++ b/mercurial/util.py Mon Dec 03 12:40:24 2012 -0800 @@ -64,7 +64,7 @@ spawndetached = platform.spawndetached split = platform.split sshargs = platform.sshargs -statfiles = platform.statfiles +statfiles = getattr(osutil, 'statfiles', platform.statfiles) termwidth = platform.termwidth testpid = platform.testpid umask = platform.umask