[PATCH 6 of 7 V4] delta: have a native implementation of _findsnapshot
Boris FELD
boris.feld at octobus.net
Wed Jan 2 17:38:15 EST 2019
On 02/01/2019 04:04, Yuya Nishihara wrote:
> On Sun, 30 Dec 2018 19:43:53 +0100, Boris Feld wrote:
>> # HG changeset patch
>> # User Boris Feld <boris.feld at octobus.net>
>> # Date 1545297320 -3600
>> # Thu Dec 20 10:15:20 2018 +0100
>> # Node ID a6bb015a9fb1a2c23d73f1c55e7d4160a9701191
>> # Parent 5aff42c50dd1bc1e7c2e533a8e052fa42c6f9304
>> # EXP-Topic sparse-revlog
>> # Available At https://bitbucket.org/octobus/mercurial-devel/
>> # hg pull https://bitbucket.org/octobus/mercurial-devel/ -r a6bb015a9fb1
>> delta: have a native implementation of _findsnapshot
>>
>> The function might traverse a lot of revision, a native implementation get
>> significantly faster.
>>
>> example affected manifest write
>> before: 0.114989
>> after: 0.067141 (-42%)
>>
>> diff --git a/mercurial/cext/revlog.c b/mercurial/cext/revlog.c
>> --- a/mercurial/cext/revlog.c
>> +++ b/mercurial/cext/revlog.c
>> @@ -1050,6 +1050,80 @@ static PyObject *index_issnapshot(indexO
>> return PyBool_FromLong((long)issnap);
>> }
>>
>> +static PyObject *index_findsnapshots(indexObject *self, PyObject *args)
>> +{
>> +
>> + Py_ssize_t start_rev;
>> + PyObject *cache;
>> + Py_ssize_t base;
>> + Py_ssize_t rev;
>> + int issnap;
>> + PyObject *key;
>> + bool newallvalues;
>> + PyObject *allvalues;
>> + PyObject *value;
> These variables have to be initialized since we do XDECREF() on failure.
Good catch, thanks!
>
>> + if (!PyArg_ParseTuple(args, "On", &cache, &start_rev)) {
>> + return NULL;
>> + }
>> + if (!PyDict_Check(cache)) {
>> + PyErr_SetString(PyExc_TypeError,
>> + "cache argument must be a dict");
>> + return NULL;
>> + }
> Nit: maybe this can be "O!" with &PyDict_Type.
I can't find if O! match subtype or only the exact type. I've delayed
this update for now.
>
>> + for (rev = start_rev; rev < length; rev++) {
>> + issnap = index_issnapshotrev(self, rev);
>> + if (issnap < 0) {
>> + goto bail;
>> + }
>> + if (issnap == 0) {
>> + continue;
>> + }
>> + base = (Py_ssize_t)index_baserev(self, rev);
>> + if (base == rev) {
>> + base = -1;
>> + }
>> + if (base == -2) {
>> + assert(PyErr_Occurred());
>> + goto bail;
>> + }
>> + key = PyInt_FromSsize_t(base);
>> + newallvalues = false;
>> + allvalues = PyDict_GetItem(cache, key);
>> + if (allvalues == NULL && PyErr_Occurred()) {
>> + goto bail;
>> + }
>> + if (allvalues == NULL) {
>> + allvalues = PyList_New(0);
> PyList_New() may fail in theory.
>
>> + newallvalues = true;
>> + if (PyDict_SetItem(cache, key, allvalues) < 0) {
>> + goto bail;
>> + }
> I prefer cleaning up the allvalues reference here for this particular case,
> so that the scope of the allvalues can be narrowed and the newallvalues can
> be eliminated.
>
> for (rev ...) {
> PyObject *allvalues; /* borrowed */
> ...
> if (allvalues == NULL) {
> int r;
> allvalues = PyList_New(0);
> if (!allvalues)
> goto bail;
> r = PyDict_SetItem(cache, key, allvalues);
> Py_DECREF(allvalues);
> if (r < 0)
> goto bail;
> }
>
>> + Py_XDECREF(key);
>> + if (newallvalues) {
>> + Py_XDECREF(allvalues);
>> + }
>> + Py_XDECREF(value);
>> + key = NULL;
>> + allvalues = NULL;
>> + value = NULL;
> Nit: Py_CLEAR() could be used in place of XDECREF() + = NULL.
>
>> + }
>> + Py_INCREF(Py_None);
>> + return Py_None;
> Nit: can be Py_RETURN_NONE;
> _______________________________________________
> Mercurial-devel mailing list
> Mercurial-devel at mercurial-scm.org
> https://www.mercurial-scm.org/mailman/listinfo/mercurial-devel
More information about the Mercurial-devel
mailing list