Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
8651a504
Commit
8651a504
authored
May 27, 2015
by
Raymond Hettinger
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Issue #23359: Specialize set_lookkey intoa lookup function and an insert function.
parent
8544e258
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
107 additions
and
41 deletions
+107
-41
Misc/NEWS
Misc/NEWS
+3
-0
Objects/setobject.c
Objects/setobject.c
+104
-41
No files found.
Misc/NEWS
View file @
8651a504
...
@@ -42,6 +42,9 @@ Core and Builtins
...
@@ -42,6 +42,9 @@ Core and Builtins
- Issue #24268: PEP 489: Multi-phase extension module initialization.
- Issue #24268: PEP 489: Multi-phase extension module initialization.
Patch by Petr Viktorin.
Patch by Petr Viktorin.
- Issue #23359: Optimize set object internals by specializing the
hash table search into a lookup function and an insert function.
- Issue #23955: Add pyvenv.cfg option to suppress registry/environment
- Issue #23955: Add pyvenv.cfg option to suppress registry/environment
lookup for generating sys.path on Windows.
lookup for generating sys.path on Windows.
...
...
Objects/setobject.c
View file @
8651a504
...
@@ -52,7 +52,6 @@ static setentry *
...
@@ -52,7 +52,6 @@ static setentry *
set_lookkey
(
PySetObject
*
so
,
PyObject
*
key
,
Py_hash_t
hash
)
set_lookkey
(
PySetObject
*
so
,
PyObject
*
key
,
Py_hash_t
hash
)
{
{
setentry
*
table
=
so
->
table
;
setentry
*
table
=
so
->
table
;
setentry
*
freeslot
=
NULL
;
setentry
*
entry
;
setentry
*
entry
;
size_t
perturb
=
hash
;
size_t
perturb
=
hash
;
size_t
mask
=
so
->
mask
;
size_t
mask
=
so
->
mask
;
...
@@ -86,14 +85,12 @@ set_lookkey(PySetObject *so, PyObject *key, Py_hash_t hash)
...
@@ -86,14 +85,12 @@ set_lookkey(PySetObject *so, PyObject *key, Py_hash_t hash)
return
entry
;
return
entry
;
mask
=
so
->
mask
;
/* help avoid a register spill */
mask
=
so
->
mask
;
/* help avoid a register spill */
}
}
if
(
entry
->
hash
==
-
1
&&
freeslot
==
NULL
)
freeslot
=
entry
;
if
(
i
+
LINEAR_PROBES
<=
mask
)
{
if
(
i
+
LINEAR_PROBES
<=
mask
)
{
for
(
j
=
0
;
j
<
LINEAR_PROBES
;
j
++
)
{
for
(
j
=
0
;
j
<
LINEAR_PROBES
;
j
++
)
{
entry
++
;
entry
++
;
if
(
entry
->
key
==
NULL
)
if
(
entry
->
hash
==
0
&&
entry
->
key
==
NULL
)
goto
found_null
;
return
entry
;
if
(
entry
->
hash
==
hash
)
{
if
(
entry
->
hash
==
hash
)
{
PyObject
*
startkey
=
entry
->
key
;
PyObject
*
startkey
=
entry
->
key
;
assert
(
startkey
!=
dummy
);
assert
(
startkey
!=
dummy
);
...
@@ -114,6 +111,89 @@ set_lookkey(PySetObject *so, PyObject *key, Py_hash_t hash)
...
@@ -114,6 +111,89 @@ set_lookkey(PySetObject *so, PyObject *key, Py_hash_t hash)
return
entry
;
return
entry
;
mask
=
so
->
mask
;
mask
=
so
->
mask
;
}
}
}
}
perturb
>>=
PERTURB_SHIFT
;
i
=
(
i
*
5
+
1
+
perturb
)
&
mask
;
entry
=
&
table
[
i
];
if
(
entry
->
hash
==
0
&&
entry
->
key
==
NULL
)
return
entry
;
}
}
/*
Internal routine to insert a new key into the table.
Used by the public insert routine.
Eats a reference to key.
*/
static
int
set_insert_key
(
PySetObject
*
so
,
PyObject
*
key
,
Py_hash_t
hash
)
{
setentry
*
table
=
so
->
table
;
setentry
*
freeslot
=
NULL
;
setentry
*
entry
;
size_t
perturb
=
hash
;
size_t
mask
=
so
->
mask
;
size_t
i
=
(
size_t
)
hash
&
mask
;
/* Unsigned for defined overflow behavior */
size_t
j
;
int
cmp
;
entry
=
&
table
[
i
];
if
(
entry
->
key
==
NULL
)
goto
found_null
;
while
(
1
)
{
if
(
entry
->
hash
==
hash
)
{
PyObject
*
startkey
=
entry
->
key
;
/* startkey cannot be a dummy because the dummy hash field is -1 */
assert
(
startkey
!=
dummy
);
if
(
startkey
==
key
)
goto
found_active
;
if
(
PyUnicode_CheckExact
(
startkey
)
&&
PyUnicode_CheckExact
(
key
)
&&
unicode_eq
(
startkey
,
key
))
goto
found_active
;
Py_INCREF
(
startkey
);
cmp
=
PyObject_RichCompareBool
(
startkey
,
key
,
Py_EQ
);
Py_DECREF
(
startkey
);
if
(
cmp
<
0
)
/* unlikely */
return
-
1
;
if
(
table
!=
so
->
table
||
entry
->
key
!=
startkey
)
/* unlikely */
return
set_insert_key
(
so
,
key
,
hash
);
if
(
cmp
>
0
)
/* likely */
goto
found_active
;
mask
=
so
->
mask
;
/* help avoid a register spill */
}
if
(
entry
->
hash
==
-
1
&&
freeslot
==
NULL
)
freeslot
=
entry
;
if
(
i
+
LINEAR_PROBES
<=
mask
)
{
for
(
j
=
0
;
j
<
LINEAR_PROBES
;
j
++
)
{
entry
++
;
if
(
entry
->
hash
==
0
&&
entry
->
key
==
NULL
)
goto
found_null
;
if
(
entry
->
hash
==
hash
)
{
PyObject
*
startkey
=
entry
->
key
;
assert
(
startkey
!=
dummy
);
if
(
startkey
==
key
)
goto
found_active
;
if
(
PyUnicode_CheckExact
(
startkey
)
&&
PyUnicode_CheckExact
(
key
)
&&
unicode_eq
(
startkey
,
key
))
goto
found_active
;
Py_INCREF
(
startkey
);
cmp
=
PyObject_RichCompareBool
(
startkey
,
key
,
Py_EQ
);
Py_DECREF
(
startkey
);
if
(
cmp
<
0
)
return
-
1
;
if
(
table
!=
so
->
table
||
entry
->
key
!=
startkey
)
return
set_insert_key
(
so
,
key
,
hash
);
if
(
cmp
>
0
)
goto
found_active
;
mask
=
so
->
mask
;
}
if
(
entry
->
hash
==
-
1
&&
freeslot
==
NULL
)
if
(
entry
->
hash
==
-
1
&&
freeslot
==
NULL
)
freeslot
=
entry
;
freeslot
=
entry
;
}
}
...
@@ -123,11 +203,26 @@ set_lookkey(PySetObject *so, PyObject *key, Py_hash_t hash)
...
@@ -123,11 +203,26 @@ set_lookkey(PySetObject *so, PyObject *key, Py_hash_t hash)
i
=
(
i
*
5
+
1
+
perturb
)
&
mask
;
i
=
(
i
*
5
+
1
+
perturb
)
&
mask
;
entry
=
&
table
[
i
];
entry
=
&
table
[
i
];
if
(
entry
->
key
==
NULL
)
if
(
entry
->
hash
==
0
&&
entry
->
key
==
NULL
)
goto
found_null
;
goto
found_null
;
}
}
found_null:
found_null:
return
freeslot
==
NULL
?
entry
:
freeslot
;
if
(
freeslot
==
NULL
)
{
/* UNUSED */
so
->
fill
++
;
}
else
{
/* DUMMY */
entry
=
freeslot
;
}
so
->
used
++
;
entry
->
key
=
key
;
entry
->
hash
=
hash
;
return
0
;
found_active:
Py_DECREF
(
key
);
return
0
;
}
}
/*
/*
...
@@ -172,38 +267,6 @@ set_insert_clean(PySetObject *so, PyObject *key, Py_hash_t hash)
...
@@ -172,38 +267,6 @@ set_insert_clean(PySetObject *so, PyObject *key, Py_hash_t hash)
/* ======== End logic for probing the hash table ========================== */
/* ======== End logic for probing the hash table ========================== */
/* ======================================================================== */
/* ======================================================================== */
/*
Internal routine to insert a new key into the table.
Used by the public insert routine.
Eats a reference to key.
*/
static
int
set_insert_key
(
PySetObject
*
so
,
PyObject
*
key
,
Py_hash_t
hash
)
{
setentry
*
entry
;
entry
=
set_lookkey
(
so
,
key
,
hash
);
if
(
entry
==
NULL
)
return
-
1
;
if
(
entry
->
key
==
NULL
)
{
/* UNUSED */
entry
->
key
=
key
;
entry
->
hash
=
hash
;
so
->
fill
++
;
so
->
used
++
;
}
else
if
(
entry
->
key
==
dummy
)
{
/* DUMMY */
entry
->
key
=
key
;
entry
->
hash
=
hash
;
so
->
used
++
;
}
else
{
/* ACTIVE */
Py_DECREF
(
key
);
}
return
0
;
}
/*
/*
Restructure the table by allocating a new table and reinserting all
Restructure the table by allocating a new table and reinserting all
keys again. When entries have been deleted, the new table may
keys again. When entries have been deleted, the new table may
...
@@ -345,7 +408,7 @@ set_discard_entry(PySetObject *so, setentry *oldentry)
...
@@ -345,7 +408,7 @@ set_discard_entry(PySetObject *so, setentry *oldentry)
entry
=
set_lookkey
(
so
,
oldentry
->
key
,
oldentry
->
hash
);
entry
=
set_lookkey
(
so
,
oldentry
->
key
,
oldentry
->
hash
);
if
(
entry
==
NULL
)
if
(
entry
==
NULL
)
return
-
1
;
return
-
1
;
if
(
entry
->
key
==
NULL
||
entry
->
key
==
dummy
)
if
(
entry
->
key
==
NULL
)
return
DISCARD_NOTFOUND
;
return
DISCARD_NOTFOUND
;
old_key
=
entry
->
key
;
old_key
=
entry
->
key
;
entry
->
key
=
dummy
;
entry
->
key
=
dummy
;
...
@@ -623,7 +686,7 @@ set_contains_entry(PySetObject *so, setentry *entry)
...
@@ -623,7 +686,7 @@ set_contains_entry(PySetObject *so, setentry *entry)
if
(
lu_entry
==
NULL
)
if
(
lu_entry
==
NULL
)
return
-
1
;
return
-
1
;
key
=
lu_entry
->
key
;
key
=
lu_entry
->
key
;
return
key
!=
NULL
&&
key
!=
dummy
;
return
key
!=
NULL
;
}
}
static
int
static
int
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment