|
|
|
Created:
1 year, 3 months ago by mark Modified:
1 year ago Reviewers:
martin, jimjjewett, benjamin CC:
loewis, rhettinger, terry.reedy, gregory.p.smith, jcea, AntoinePitrou, haypo, pjenvey, Benjamin Peterson, Yury.Selivanov, Mark.Shannon, devnull_psf.upfronthosting.co.za, jcon, Jim.Jewett Visibility:
Public. |
Patch Set 1 #Patch Set 2 #
Total comments: 21
Patch Set 3 #Patch Set 4 #Patch Set 5 #Patch Set 6 #Patch Set 7 #Patch Set 8 #Patch Set 9 #Patch Set 10 #Patch Set 11 #
Total comments: 99
Patch Set 12 #Patch Set 13 #Patch Set 14 #Patch Set 15 #Patch Set 16 #Patch Set 17 #
Total comments: 3
Patch Set 18 #
Created: 1 year ago
MessagesTotal messages: 5
I skipped over some of the chunks due to shortage of time right now; I may reconsider these after a new version of the patch. General remark: please elaborate more using comments. http://bugs.python.org/review/13903/diff/4082/13744 File Include/dictobject.h (right): http://bugs.python.org/review/13903/diff/4082/13744#newcode120 Include/dictobject.h:120: PyAPI_FUNC(PyObject *) PyDict_NewForInstance(PyTypeObject *tp); Do these need to be public APIs? If not, add an underscore. If yes, make sure they are documented. http://bugs.python.org/review/13903/diff/4082/13744#newcode137 Include/dictobject.h:137: white-space only change http://bugs.python.org/review/13903/diff/4082/13745 File Include/object.h (right): http://bugs.python.org/review/13903/diff/4082/13745#newcode451 Include/object.h:451: struct _dictkeysobject *ht_cached_keys; Why is this done only for heap types? If that's intentional, add a comment. http://bugs.python.org/review/13903/diff/4082/13750 File Lib/test/test_pprint.py (right): http://bugs.python.org/review/13903/diff/4082/13750#newcode248 Lib/test/test_pprint.py:248: Testing the set repr is certainly a useful thing to do. Wrt. the cube repr, I think it's ok to drop the test. Alternatively, delete all the non-orderable keys from the dict, using del, e.g. {1},{2},{0,2},{1,2} (i.e. leaving only {}, {0}, {0,1}, {0,1,2}). http://bugs.python.org/review/13903/diff/4082/13751 File Lib/test/test_sys.py (right): http://bugs.python.org/review/13903/diff/4082/13751#newcode688 Lib/test/test_sys.py:688: # Less exposure of implementation details please! This most certainly is a meaningful test. There is a deterministic correct result (given the current implementation); the test purpose is to determine whether the size computation of the dictionary worked correctly. It may be that size computation becomes difficult given shared keys. You need to find a way to make it work "correctly", where "correctly" means "when summing up the sizes of all allocated objects, the amount should equal the memory that was actually allocated". http://bugs.python.org/review/13903/diff/4082/13752 File Lib/weakref.py (right): http://bugs.python.org/review/13903/diff/4082/13752#newcode267 Lib/weakref.py:267: except KeyError: Please explain: why can you get KeyErrors now? http://bugs.python.org/review/13903/diff/4082/13754 File Objects/dictobject.c (right): http://bugs.python.org/review/13903/diff/4082/13754#newcode191 Objects/dictobject.c:191: static PyDictObject *free_list_d[PyDict_MAXFREELIST]; Is it really necessary to maintain separate freelists? How much speed is lost without them? http://bugs.python.org/review/13903/diff/4082/13754#newcode227 Objects/dictobject.c:227: static PyObject *empty_values[8] = { Please add a comment explaining what this is for. http://bugs.python.org/review/13903/diff/4082/13754#newcode235 Objects/dictobject.c:235: struct keys_8 { This structure appears to be unused, except for the empty keys. Please comment how this is used, and why. http://bugs.python.org/review/13903/diff/4082/13754#newcode559 Objects/dictobject.c:559: a faster lookup can be used. */ How is it "faster"? Elaborate. http://bugs.python.org/review/13903/diff/4082/13754#newcode868 Objects/dictobject.c:868: white-space-only change. http://bugs.python.org/review/13903/diff/4082/13754#newcode1170 Objects/dictobject.c:1170: white-space-only change. http://bugs.python.org/review/13903/diff/4082/13754#newcode1204 Objects/dictobject.c:1204: Py_INCREF(key); So why INCREF(key)? The comment says to INCREF(value) (which also happens, one line below). http://bugs.python.org/review/13903/diff/4082/13754#newcode1743 Objects/dictobject.c:1743: /* Debugging function for (partly) verifying invariants */ Should be available only in debug build. http://bugs.python.org/review/13903/diff/4082/13754#newcode2181 Objects/dictobject.c:2181: /* Count our share of the keys object -- with rounding errors. */ For this application, it would actually be better if the keys were a proper Python object, and a dictionary property would allow to get hold of it. Memory profilers could then deal with it separately. [I know I suggested to move away from Python objects here; I'm really not sure what the best strategy is] http://bugs.python.org/review/13903/diff/4082/13754#newcode2513 Objects/dictobject.c:2513: ws change http://bugs.python.org/review/13903/diff/4082/13754#newcode3234 Objects/dictobject.c:3234: ws change. http://bugs.python.org/review/13903/diff/4082/13754#newcode3301 Objects/dictobject.c:3301: int PyObjectDict_SetItem(PyTypeObject *tp, PyObject **dictptr, PyObject *name, PyObject *value) { This looks like an internal routine, too. http://bugs.python.org/review/13903/diff/4082/13755 File Objects/moduleobject.c (right): http://bugs.python.org/review/13903/diff/4082/13755#newcode288 Objects/moduleobject.c:288: if (PyUnicode_READ_CHAR(key, 0) == '_' && Unrelated change. http://bugs.python.org/review/13903/diff/4082/13756 File Objects/object.c (right): http://bugs.python.org/review/13903/diff/4082/13756#newcode1167 Objects/object.c:1167: if (res < 0 && PyErr_ExceptionMatches(PyExc_KeyError)) Why can you get a KeyError here? http://bugs.python.org/review/13903/diff/4082/13756#newcode1171 Objects/object.c:1171: } else { line-break before else
Sign in to reply to this message.
Include/dictobject.h ==================== Reducing PyDict_MINSIZE from 8 to 4: I suspect this is probably a good change, but it is worth mentioning in the changes, and worth measuring. How many dicts really have only 2 (or now 3?) values, vs the cost of an extra resize? Renaming PyDictEntry to PyDictKeyEntry: Why? Personally, I consider its structure to be an internal detail, and would like to see it removed from the header (or at least put in a more private header, like dictobjectimpl.h). But if it is being kept, it might make sense to keep the name as well; the combined dicts use is as a full entry, and the split dicts go out of their way to fill it in as if it were a regular entry. dict_lookup_func should probably also be moved to a more private location. Even if it is moved (and especially if it isn't), you should not assume that the current list is exhaustive. Keeping it public suggests that 3rd party extensions will be supplying their own *internal-format* lookup funcs; they might, and there are use cases, but I think they should know that they are messing with internals when they do. _dictkeysobject should probably also be in a more private location; the only external usage I found (in object.h) was just a pointer, and didn't need to know what the structure looked like. Lib/Test/test_pprint.py ======================= I agree that the format of set(range(3)) is problematic, but the printing of the empty sets is clearly a valid test. For the other tests, I think it is wrong to just stop running them. At a minimum, the test should be copied to another with a @skip decorator. Personally, I would prefer that pprint do the same thing with sets that it already does with dicts, and just order the keys if it can. (Since it can for these tests, that would solve the issue.) Objects/dictnotes.txt ===================== Please leave the note about builtins being all interned strings; just update the size to 133 as 3.2, or something newer. The notes about cache line counts for larger dicts and Cache Locality Experiments still apply to combined dicts, and to the keys table. Go ahead and reword it, but please don't delete it. It is worth noting here that PyDict_MINSIZE was 8 prior to python 3.3, so that people realize it is a recent change. Particularly leave the discussion of why flipping the last bit might be OK, but linear probing isn't. The outcome of the hash randomization *might* make it easier to change to iteration order in the future. Objects/dictobject.c ==================== Line numbers are based on https://bitbucket.org/markshannon/cpython_new_dict/compare/..mirror/cpython -- not sure if that is the same version as this patch. Why the removals around line 28-31 and 144-190? These are still useful comments, and the #undef is still a useful compile-time flag. Around 180, you're reinventing ref-counting; just making the keys a PyObject costs only a single pointer (for type), except when debugging is turned on and you might want the extra information. Note that this would also take care of using the GC trashcan macros for you. At 186, I think this can be worded a bit more clearly. Maybe: /* USABLE_FRACTION must obey the following: * (0 < USABLE_FRACTION(n) < n) for all n >= PyDict_MINSIZE * * USABLE_FRACTION should be very quick to calculate. * Fractions around 5/8 to 2/3 seem to work well in practice. */ I'm also pretty sure that the previous code (multiplying both sides, to avoid adding or dividing) was tuned for speed; don't give that up with without measurements. Using two multiplies also has the advantage of leaving dk_free with a more intuitive meaning. (count of free slots, rather than count of still-usable slots.) Line 206 -- Why is lookdict (the generic, might not even be a string key) not deletable? Line 246 -- Why not just memset the whole thing to 0? Line 308-309 why not just memset the values to NULL? Line 312-316 -- Why was this deleted? The removal suggests that it no longer returns the place where a key would be inserted. Line 397-406 -- why remove these comments? Particularly since you're still insisting on PyUnicode_CheckExact? Line 604 (old 466): What if the lookdict is something custom from a subclass? I think it would be safer to check for the functions that you do expect. Line 674 (old 528): Why remove the register declaration? Line 746 (old 572): Why remove the register declaration? Line 997 (old 793): Why remove the register declaration? Line 999-1000 (old 795-797): Why remove the register declaration? Line 1025-1027 (old 841-843): Why remove the register declaration? (just make it a global comment) Line 832-833: Why null the memory out if it is just being deallocated? Addresses shouldn't be particularly sensitive even if it were going all the way to the OS. Line 860 seems redundant, given lines 857 and 859. old lines 818-832: The info about growth rate (and possible shrinkage) is worth documenting, though I suppose it should move nearer the actual (current) calculation. Line 1082: Where is empty_values INCREFed? Global -- what makes a keytable immutable? Is that something user python code (or extension code) should be able to do? To undo? What exactly happens if a shared keytable needs to be resized up? I think you've answered that in email, but I didn't really find clear comments about it in the code. -jJ
Sign in to reply to this message.
I mostly have endless stylistic complaints. http://bugs.python.org/review/13903/diff/4567/16188 File Include/dictobject.h (right): http://bugs.python.org/review/13903/diff/4567/16188#newcode109 Include/dictobject.h:109: int _PyObjectDict_SetItem(PyTypeObject *tp, PyObject **dictptr, PyObject *name, PyObject *value); I think you're forgetting the PyAPI_FUNC macros, here. http://bugs.python.org/review/13903/diff/4567/16189 File Include/object.h (right): http://bugs.python.org/review/13903/diff/4567/16189#newcode452 Include/object.h:452: struct _dictkeysobject *ht_cached_keys; Why not say "PyDictKeysObject"? http://bugs.python.org/review/13903/diff/4567/16191 File Lib/test/test_pprint.py (right): http://bugs.python.org/review/13903/diff/4567/16191#newcode252 Lib/test/test_pprint.py:252: return It'd be better to use an expectedFailure. http://bugs.python.org/review/13903/diff/4567/16193 File Objects/dictnotes.txt (right): http://bugs.python.org/review/13903/diff/4567/16193#newcode2 Objects/dictnotes.txt:2: ================================ Adjust this. http://bugs.python.org/review/13903/diff/4567/16193#newcode23 Objects/dictnotes.txt:23: Size 147 interned strings (as of Py3.3a0). We're past alpha 0 now. http://bugs.python.org/review/13903/diff/4567/16193#newcode62 Objects/dictnotes.txt:62: ---------------------------------------------------------------- Adjust this. http://bugs.python.org/review/13903/diff/4567/16193#newcode88 Objects/dictnotes.txt:88: Currently set to 2/3. Wrap next line into this. http://bugs.python.org/review/13903/diff/4567/16194 File Objects/dictobject.c (right): http://bugs.python.org/review/13903/diff/4567/16194#newcode12 Objects/dictobject.c:12: There are four kinds of slots in the table: It might be nice to make predicate macros for these various states like SLOT_PENDING/ACTIVE/DUMMY/UNUSED. Then, below, where you are checking invariants, you could use them. It would be more clear what you check for in the assertions below. http://bugs.python.org/review/13903/diff/4567/16194#newcode76 Objects/dictobject.c:76: PyObject *_me_value; /* This field is only meaningful for combined tables */ Why the underscore prefix? http://bugs.python.org/review/13903/diff/4567/16194#newcode236 Objects/dictobject.c:236: static int This might as well be on one line. http://bugs.python.org/review/13903/diff/4567/16194#newcode291 Objects/dictobject.c:291: #define ENSURE_ALLOWS_DELETIONS(d) \ Can this be a static function? http://bugs.python.org/review/13903/diff/4567/16194#newcode313 Objects/dictobject.c:313: static PyDictKeysObject *new_keys_object(Py_ssize_t size) { Function name on separate line and brace on its own line like other functions. http://bugs.python.org/review/13903/diff/4567/16194#newcode320 Objects/dictobject.c:320: dk = PyMem_Malloc(sizeof(PyDictKeysObject) + It's usually preferable to use the macros version: PyMem_MALLOC http://bugs.python.org/review/13903/diff/4567/16194#newcode349 Objects/dictobject.c:349: PyMem_DEL(keys); This is deprecate in favor of PyMem_FREE. http://bugs.python.org/review/13903/diff/4567/16194#newcode352 Objects/dictobject.c:352: #define new_values(size) PyMem_New(PyObject *, size) PyMem_NEW http://bugs.python.org/review/13903/diff/4567/16194#newcode354 Objects/dictobject.c:354: #define free_values(values) PyMem_DEL(values) Same comment about PyMem_DEL being deprecated applies. http://bugs.python.org/review/13903/diff/4567/16194#newcode383 Objects/dictobject.c:383: new_dict_with_shared_keys(PyDictKeysObject *keys) { Brace on next line. http://bugs.python.org/review/13903/diff/4567/16194#newcode393 Objects/dictobject.c:393: for (i = 0; i < size; i++) { Why not memset? http://bugs.python.org/review/13903/diff/4567/16194#newcode400 Objects/dictobject.c:400: PyDict_New(void) { Brace on next line? http://bugs.python.org/review/13903/diff/4567/16194#newcode401 Objects/dictobject.c:401: return new_dict(new_keys_object(PyDict_MINSIZE_COMBINED), NULL); What if new_keys_object fails? http://bugs.python.org/review/13903/diff/4567/16194#newcode436 Objects/dictobject.c:436: register size_t mask = (size_t)mp->ma_keys->dk_size-1; Do you want to use the DK_SIZE macro? http://bugs.python.org/review/13903/diff/4567/16194#newcode527 Objects/dictobject.c:527: register size_t mask = (size_t)mp->ma_keys->dk_size-1; Ditto note about DK_SIZE. http://bugs.python.org/review/13903/diff/4567/16194#newcode610 Objects/dictobject.c:610: if (ep->me_hash == hash && unicode_eq(ep->me_key, key)) { This and the last if can be folded together. http://bugs.python.org/review/13903/diff/4567/16194#newcode622 Objects/dictobject.c:622: if (ep->me_hash == hash && unicode_eq(ep->me_key, key)) { This if can be folded with the last one. http://bugs.python.org/review/13903/diff/4567/16194#newcode637 Objects/dictobject.c:637: Py_hash_t hash, PyObject ***value_addr) Fix alignment. http://bugs.python.org/review/13903/diff/4567/16194#newcode646 Objects/dictobject.c:646: return lookdict(mp, key, hash, value_addr); Need to set the lookdict pointer on keys, too? http://bugs.python.org/review/13903/diff/4567/16194#newcode655 Objects/dictobject.c:655: if (ep->me_hash == hash && unicode_eq(ep->me_key, key)) { Fold ifs. http://bugs.python.org/review/13903/diff/4567/16194#newcode667 Objects/dictobject.c:667: if (ep->me_hash == hash && unicode_eq(ep->me_key, key)) { Same comment about folding condition. http://bugs.python.org/review/13903/diff/4567/16194#newcode718 Objects/dictobject.c:718: assert(!_PyObject_GC_MAY_BE_TRACKED(mp->ma_keys->dk_entries[i].me_key)); Wrap. http://bugs.python.org/review/13903/diff/4567/16194#newcode722 Objects/dictobject.c:722: } else { Prevailing conventions seems to like the first brace to be on its own line. http://bugs.python.org/review/13903/diff/4567/16194#newcode735 Objects/dictobject.c:735: /* Internal function to find slot for an item, from its hash, Commas not needed. http://bugs.python.org/review/13903/diff/4567/16194#newcode791 Objects/dictobject.c:791: if (mp->ma_values != NULL) { This whole chain of ifs can be in one condition. http://bugs.python.org/review/13903/diff/4567/16194#newcode811 Objects/dictobject.c:811: } else { else { on its own line. http://bugs.python.org/review/13903/diff/4567/16194#newcode826 Objects/dictobject.c:826: } else { Ditto. http://bugs.python.org/review/13903/diff/4567/16194#newcode898 Objects/dictobject.c:898: Py_ssize_t i, size; The name "oldsize" might be better. http://bugs.python.org/review/13903/diff/4567/16194#newcode913 Objects/dictobject.c:913: if (oldkeys->dk_lookup == lookdict) Do this after checking that mp->ma_keys is not NULL. http://bugs.python.org/review/13903/diff/4567/16194#newcode923 Objects/dictobject.c:923: assert(oldkeys = Py_EMPTY_KEYS); I think you meant ==. http://bugs.python.org/review/13903/diff/4567/16194#newcode932 Objects/dictobject.c:932: for (i = 0; i < size; i++) Put braces around this body. http://bugs.python.org/review/13903/diff/4567/16194#newcode965 Objects/dictobject.c:965: PyMem_DEL(oldkeys); PyMem_FREE http://bugs.python.org/review/13903/diff/4567/16194#newcode971 Objects/dictobject.c:971: make_keys_shared(PyObject *op) { Brace on next line. http://bugs.python.org/review/13903/diff/4567/16194#newcode983 Objects/dictobject.c:983: } else if (mp->ma_keys->dk_lookup == lookdict_unicode) { 2 lines. http://bugs.python.org/review/13903/diff/4567/16194#newcode985 Objects/dictobject.c:985: if (dictresize(mp, DK_SIZE(mp->ma_keys))) Fold into above condition. http://bugs.python.org/review/13903/diff/4567/16194#newcode992 Objects/dictobject.c:992: if (values == NULL) Need to set memory error. http://bugs.python.org/review/13903/diff/4567/16194#newcode994 Objects/dictobject.c:994: size = DK_SIZE(mp->ma_keys); Set size before 991 and then use it there. http://bugs.python.org/review/13903/diff/4567/16194#newcode1014 Objects/dictobject.c:1014: return new_dict(new_keys_object(newsize), NULL); What if new_keys_object fails? http://bugs.python.org/review/13903/diff/4567/16194#newcode1110 Objects/dictobject.c:1110: _PyDict_LoadGlobal(PyDictObject *globals, PyDictObject* builtins, PyObject *key) Fix PyDictObject* start. http://bugs.python.org/review/13903/diff/4567/16194#newcode1279 Objects/dictobject.c:1279: if (mp->ma_values) { It would be nice if the whole iteration boilerplate could be abstracted into a function or macro somehow. http://bugs.python.org/review/13903/diff/4567/16194#newcode1402 Objects/dictobject.c:1402: /* Prevent repr from deleting value during key format. */ "deleting value" -> "deleting key and value" http://bugs.python.org/review/13903/diff/4567/16194#newcode2309 Objects/dictobject.c:2309: if (dictresize(mp, DK_SIZE(mp->ma_keys))) { Fold with if on last line. http://bugs.python.org/review/13903/diff/4567/16194#newcode2403 Objects/dictobject.c:2403: return PyFloat_FromDouble(res); Hmm, I'm not so sure about this. Is returning a float useful? http://bugs.python.org/review/13903/diff/4567/16194#newcode3599 Objects/dictobject.c:3599: PyObject *key, PyObject *value) { Put brace on next line. http://bugs.python.org/review/13903/diff/4567/16194#newcode3614 Objects/dictobject.c:3614: *dictptr = dict; There's no point in doing this if you didn't just create a dict. http://bugs.python.org/review/13903/diff/4567/16194#newcode3626 Objects/dictobject.c:3626: CACHED_KEYS(tp) = make_keys_shared(dict); What if this fails? http://bugs.python.org/review/13903/diff/4567/16196 File Objects/typeobject.c (right): http://bugs.python.org/review/13903/diff/4567/16196#newcode2310 Objects/typeobject.c:2310: et->ht_cached_keys = _PyDict_NewKeysForClass(); Check for failure? http://bugs.python.org/review/13903/diff/4567/16196#newcode2418 Objects/typeobject.c:2418: res->ht_cached_keys = _PyDict_NewKeysForClass(); And here? http://bugs.python.org/review/13903/diff/4567/16196#newcode2776 Objects/typeobject.c:2776: extern void Shouldn't this be in dictobject.h instead?
Sign in to reply to this message.
All fixed. I've mostly followed Benjamin's recommendations with a few minor stylistic differences which I've explained. http://bugs.python.org/review/13903/diff/4567/16189 File Include/object.h (right): http://bugs.python.org/review/13903/diff/4567/16189#newcode452 Include/object.h:452: struct _dictkeysobject *ht_cached_keys; On 2012/04/20 04:33:19, Benjamin Peterson wrote: > Why not say "PyDictKeysObject"? To avoid object.h depending on dictobject.h http://bugs.python.org/review/13903/diff/4567/16191 File Lib/test/test_pprint.py (right): http://bugs.python.org/review/13903/diff/4567/16191#newcode252 Lib/test/test_pprint.py:252: return On 2012/04/20 04:33:19, Benjamin Peterson wrote: > It'd be better to use an expectedFailure. Done. http://bugs.python.org/review/13903/diff/4567/16193 File Objects/dictnotes.txt (right): http://bugs.python.org/review/13903/diff/4567/16193#newcode23 Objects/dictnotes.txt:23: Size 147 interned strings (as of Py3.3a0). On 2012/04/20 04:33:19, Benjamin Peterson wrote: > We're past alpha 0 now. Done. http://bugs.python.org/review/13903/diff/4567/16193#newcode62 Objects/dictnotes.txt:62: ---------------------------------------------------------------- On 2012/04/20 04:33:19, Benjamin Peterson wrote: > Adjust this. Done. http://bugs.python.org/review/13903/diff/4567/16193#newcode88 Objects/dictnotes.txt:88: Currently set to 2/3. On 2012/04/20 04:33:19, Benjamin Peterson wrote: > Wrap next line into this. Done. http://bugs.python.org/review/13903/diff/4567/16194 File Objects/dictobject.c (right): http://bugs.python.org/review/13903/diff/4567/16194#newcode12 Objects/dictobject.c:12: There are four kinds of slots in the table: On 2012/04/20 04:33:19, Benjamin Peterson wrote: > It might be nice to make predicate macros for these various states like > SLOT_PENDING/ACTIVE/DUMMY/UNUSED. Then, below, where you are checking > invariants, you could use them. It would be more clear what you check for in the > assertions below. Most of the assertions are checking other things, so I don't think the macros would be worthwhile. http://bugs.python.org/review/13903/diff/4567/16194#newcode76 Objects/dictobject.c:76: PyObject *_me_value; /* This field is only meaningful for combined tables */ On 2012/04/20 04:33:19, Benjamin Peterson wrote: > Why the underscore prefix? I removed the prefix. I had used it previously as PyDictKeyEntry was originally declared in dictobject.h and I wanted to make it extra clear that this field should not be accessed by other code. http://bugs.python.org/review/13903/diff/4567/16194#newcode236 Objects/dictobject.c:236: static int On 2012/04/20 04:33:19, Benjamin Peterson wrote: > This might as well be on one line. Done. http://bugs.python.org/review/13903/diff/4567/16194#newcode291 Objects/dictobject.c:291: #define ENSURE_ALLOWS_DELETIONS(d) \ On 2012/04/20 04:33:19, Benjamin Peterson wrote: > Can this be a static function? It could be, but as it should always be inlined its probably better as a macro. http://bugs.python.org/review/13903/diff/4567/16194#newcode313 Objects/dictobject.c:313: static PyDictKeysObject *new_keys_object(Py_ssize_t size) { On 2012/04/20 04:33:19, Benjamin Peterson wrote: > Function name on separate line and brace on its own line like other functions. Done. http://bugs.python.org/review/13903/diff/4567/16194#newcode320 Objects/dictobject.c:320: dk = PyMem_Malloc(sizeof(PyDictKeysObject) + On 2012/04/20 04:33:19, Benjamin Peterson wrote: > It's usually preferable to use the macros version: PyMem_MALLOC Done. http://bugs.python.org/review/13903/diff/4567/16194#newcode349 Objects/dictobject.c:349: PyMem_DEL(keys); On 2012/04/20 04:33:19, Benjamin Peterson wrote: > This is deprecate in favor of PyMem_FREE. Done. http://bugs.python.org/review/13903/diff/4567/16194#newcode352 Objects/dictobject.c:352: #define new_values(size) PyMem_New(PyObject *, size) On 2012/04/20 04:33:19, Benjamin Peterson wrote: > PyMem_NEW Done. http://bugs.python.org/review/13903/diff/4567/16194#newcode354 Objects/dictobject.c:354: #define free_values(values) PyMem_DEL(values) On 2012/04/20 04:33:19, Benjamin Peterson wrote: > Same comment about PyMem_DEL being deprecated applies. Done. http://bugs.python.org/review/13903/diff/4567/16194#newcode383 Objects/dictobject.c:383: new_dict_with_shared_keys(PyDictKeysObject *keys) { On 2012/04/20 04:33:19, Benjamin Peterson wrote: > Brace on next line. Done. http://bugs.python.org/review/13903/diff/4567/16194#newcode393 Objects/dictobject.c:393: for (i = 0; i < size; i++) { On 2012/04/20 04:33:19, Benjamin Peterson wrote: > Why not memset? Because memset is only faster for large or unaligned memory. For small aligned memory (and shared-keys dict are small) the loop is faster, unless the compiler is smart enough to perform the substitution itself. Many aren't. http://bugs.python.org/review/13903/diff/4567/16194#newcode400 Objects/dictobject.c:400: PyDict_New(void) { On 2012/04/20 04:33:19, Benjamin Peterson wrote: > Brace on next line? Done. http://bugs.python.org/review/13903/diff/4567/16194#newcode436 Objects/dictobject.c:436: register size_t mask = (size_t)mp->ma_keys->dk_size-1; On 2012/04/20 04:33:19, Benjamin Peterson wrote: > Do you want to use the DK_SIZE macro? I've added a DK_MASK macro and used that throughout. http://bugs.python.org/review/13903/diff/4567/16194#newcode610 Objects/dictobject.c:610: if (ep->me_hash == hash && unicode_eq(ep->me_key, key)) { On 2012/04/20 04:33:19, Benjamin Peterson wrote: > This and the last if can be folded together. Done. http://bugs.python.org/review/13903/diff/4567/16194#newcode622 Objects/dictobject.c:622: if (ep->me_hash == hash && unicode_eq(ep->me_key, key)) { On 2012/04/20 04:33:19, Benjamin Peterson wrote: > This if can be folded with the last one. Done. http://bugs.python.org/review/13903/diff/4567/16194#newcode637 Objects/dictobject.c:637: Py_hash_t hash, PyObject ***value_addr) On 2012/04/20 04:33:19, Benjamin Peterson wrote: > Fix alignment. Done. http://bugs.python.org/review/13903/diff/4567/16194#newcode646 Objects/dictobject.c:646: return lookdict(mp, key, hash, value_addr); On 2012/04/20 04:33:19, Benjamin Peterson wrote: > Need to set the lookdict pointer on keys, too? No. mp->ma_keys->dk_lookup <=> _PyDict_HasSplitTable(mp) For a split table, only the lookdict_split will work and lookdict_split requires a split table. I've added a comment. http://bugs.python.org/review/13903/diff/4567/16194#newcode655 Objects/dictobject.c:655: if (ep->me_hash == hash && unicode_eq(ep->me_key, key)) { On 2012/04/20 04:33:19, Benjamin Peterson wrote: > Fold ifs. Done. http://bugs.python.org/review/13903/diff/4567/16194#newcode667 Objects/dictobject.c:667: if (ep->me_hash == hash && unicode_eq(ep->me_key, key)) { On 2012/04/20 04:33:19, Benjamin Peterson wrote: > Same comment about folding condition. Done. http://bugs.python.org/review/13903/diff/4567/16194#newcode791 Objects/dictobject.c:791: if (mp->ma_values != NULL) { On 2012/04/20 04:33:19, Benjamin Peterson wrote: > This whole chain of ifs can be in one condition. I've put the first two together as they form the test, whereas the third is the action (the test is to check for an error) http://bugs.python.org/review/13903/diff/4567/16194#newcode898 Objects/dictobject.c:898: Py_ssize_t i, size; On 2012/04/20 04:33:19, Benjamin Peterson wrote: > The name "oldsize" might be better. Done. http://bugs.python.org/review/13903/diff/4567/16194#newcode913 Objects/dictobject.c:913: if (oldkeys->dk_lookup == lookdict) On 2012/04/20 04:33:19, Benjamin Peterson wrote: > Do this after checking that mp->ma_keys is not NULL. Done. http://bugs.python.org/review/13903/diff/4567/16194#newcode923 Objects/dictobject.c:923: assert(oldkeys = Py_EMPTY_KEYS); On 2012/04/20 04:33:19, Benjamin Peterson wrote: > I think you meant ==. Done. http://bugs.python.org/review/13903/diff/4567/16194#newcode983 Objects/dictobject.c:983: } else if (mp->ma_keys->dk_lookup == lookdict_unicode) { On 2012/04/20 04:33:19, Benjamin Peterson wrote: > 2 lines. Done. http://bugs.python.org/review/13903/diff/4567/16194#newcode985 Objects/dictobject.c:985: if (dictresize(mp, DK_SIZE(mp->ma_keys))) On 2012/04/20 04:33:19, Benjamin Peterson wrote: > Fold into above condition. I prefer not to as the second "condition" is really an action, the test is for an exception. http://bugs.python.org/review/13903/diff/4567/16194#newcode992 Objects/dictobject.c:992: if (values == NULL) On 2012/04/20 04:33:19, Benjamin Peterson wrote: > Need to set memory error. Done. http://bugs.python.org/review/13903/diff/4567/16194#newcode994 Objects/dictobject.c:994: size = DK_SIZE(mp->ma_keys); On 2012/04/20 04:33:19, Benjamin Peterson wrote: > Set size before 991 and then use it there. Done. http://bugs.python.org/review/13903/diff/4567/16194#newcode1014 Objects/dictobject.c:1014: return new_dict(new_keys_object(newsize), NULL); On 2012/04/20 04:33:19, Benjamin Peterson wrote: > What if new_keys_object fails? Done. http://bugs.python.org/review/13903/diff/4567/16194#newcode1110 Objects/dictobject.c:1110: _PyDict_LoadGlobal(PyDictObject *globals, PyDictObject* builtins, PyObject *key) On 2012/04/20 04:33:19, Benjamin Peterson wrote: > Fix PyDictObject* start. Done. http://bugs.python.org/review/13903/diff/4567/16194#newcode1402 Objects/dictobject.c:1402: /* Prevent repr from deleting value during key format. */ On 2012/04/20 04:33:19, Benjamin Peterson wrote: > "deleting value" -> "deleting key and value" Done. http://bugs.python.org/review/13903/diff/4567/16194#newcode2309 Objects/dictobject.c:2309: if (dictresize(mp, DK_SIZE(mp->ma_keys))) { On 2012/04/20 04:33:19, Benjamin Peterson wrote: > Fold with if on last line. Same argument as before, dictresize is an action, not a condition. http://bugs.python.org/review/13903/diff/4567/16194#newcode2403 Objects/dictobject.c:2403: return PyFloat_FromDouble(res); On 2012/04/20 04:33:19, Benjamin Peterson wrote: > Hmm, I'm not so sure about this. Is returning a float useful? I'm not sure about this either. But how do we divide up the shared keys if returning an int? http://bugs.python.org/review/13903/diff/4567/16194#newcode3599 Objects/dictobject.c:3599: PyObject *key, PyObject *value) { On 2012/04/20 04:33:19, Benjamin Peterson wrote: > Put brace on next line. Done. http://bugs.python.org/review/13903/diff/4567/16194#newcode3614 Objects/dictobject.c:3614: *dictptr = dict; On 2012/04/20 04:33:19, Benjamin Peterson wrote: > There's no point in doing this if you didn't just create a dict. Done. http://bugs.python.org/review/13903/diff/4567/16194#newcode3626 Objects/dictobject.c:3626: CACHED_KEYS(tp) = make_keys_shared(dict); On 2012/04/20 04:33:19, Benjamin Peterson wrote: > What if this fails? Done. http://bugs.python.org/review/13903/diff/4567/16196 File Objects/typeobject.c (right): http://bugs.python.org/review/13903/diff/4567/16196#newcode2310 Objects/typeobject.c:2310: et->ht_cached_keys = _PyDict_NewKeysForClass(); On 2012/04/20 04:33:19, Benjamin Peterson wrote: > Check for failure? et->ht_cached_keys == NULL is a valid state. I've altered _PyDict_NewKeysForClass so as not set an error. http://bugs.python.org/review/13903/diff/4567/16196#newcode2418 Objects/typeobject.c:2418: res->ht_cached_keys = _PyDict_NewKeysForClass(); On 2012/04/20 04:33:19, Benjamin Peterson wrote: > And here? Ditto http://bugs.python.org/review/13903/diff/4567/16196#newcode2776 Objects/typeobject.c:2776: extern void On 2012/04/20 04:33:19, Benjamin Peterson wrote: > Shouldn't this be in dictobject.h instead? _PyDictKeys_DecRef is not a public function. This is the only use of it. An alternative might be to move the dictobject structs and macros into a dictobject_impl.h and include that in this file.
Sign in to reply to this message.
Worthwhile addition. I've made a couple of comments. http://bugs.python.org/review/13903/diff/4766/16903 File Objects/dictobject.c (right): http://bugs.python.org/review/13903/diff/4766/16903#newcode265 Objects/dictobject.c:265: #define DK_DEBUG_DECREF _Py_DEC_REFTOTAL _Py_REF_DEBUG_COMMA I don't think we should use _Py_INC_REFTOTAL as the keys are not PyObjects. Could you add a DK_RefTotal value, or does that make checking for leaks awkard? http://bugs.python.org/review/13903/diff/4766/16903#newcode1269 Objects/dictobject.c:1269: DK_DECREF(oldkeys); Could you replace the free_keys_object() call with a macro that would include the assert and DK_DEBUG_DECREF? I would like to keep the assertion as (keys->dk_refcnt == 1) for combined tables is an important invariant. http://bugs.python.org/review/13903/diff/4766/16903#newcode1378 Objects/dictobject.c:1378: DK_DECREF(keys); Ditto.
Sign in to reply to this message.
|
||||||||||||||||||||||||||||||||||||||