Issue 20519: Replace uuid ctypes usage with an extension module. (original) (raw)

Issue20519

Created on 2014-02-05 11:52 by gustavo, last changed 2022-04-11 14:57 by admin. This issue is now closed.

Files
File name Uploaded Description Edit
gc.py gustavo,2014-02-05 11:52 test program
uuid-no-ctypes.diff gustavo,2014-02-05 16:16 review
issue20519_10941v2.diff gustavo,2015-10-26 19:14 review
uuid.diff gustavo,2015-10-28 13:36 review
Pull Requests
URL Status Linked Edit
PR 3796 merged pitrou,2017-09-28 10:37
Messages (17)
msg210306 - (view) Author: Gustavo J. A. M. Carneiro (gustavo) * Date: 2014-02-05 11:52
If you try the attached program, you will find that for every iteration the uuid.uuid4() call generates objects that contain reference cycles and need the help of the garbage collector. This is not nice. If I make the ctypes module not able to import, then no garbage is generated. This problem appears in 2.7, 3.3, and 3.4, at least.
msg210316 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2014-02-05 14:10
I'm not sure that this is a real problem, but have you identified what the cycle is?
msg210320 - (view) Author: Gustavo J. A. M. Carneiro (gustavo) * Date: 2014-02-05 14:28
Well, this isn't a big problem, but I have an application that needs to run with the GC disabled, since it causes pauses of a couple of seconds each time a full collection runs (we have a few million objects allocated). I will run the GC only once every 3 hours. So it would be nice if this uuid call didn't generate cycles. No, I didn't identify the cycle. All I know is that the garbage below is produced. If the ctypes module is unavailable, uuid still works but doesn't generate the garbage. >>> gc.garbage [(<type '_ctypes.Array'>,), {'raw': <attribute 'raw' of 'c_char_Array_16' objects>, '__module__': 'ctypes', '__dict__': <attribute '__dict__' of 'c_char_Array_16' objects>, '__weakref__': <attribute '__weakref__' of 'c_char_Array_16' objects>, '_length_': 16, '_type_': <class 'ctypes.c_char'>, '__doc__': None, 'value': <attribute 'value' of 'c_char_Array_16' objects>}, <class 'ctypes.c_char_Array_16'>, <attribute '__dict__' of 'c_char_Array_16' objects>, <attribute '__weakref__' of 'c_char_Array_16' objects>, (<class 'ctypes.c_char_Array_16'>, <type '_ctypes.Array'>, <type '_ctypes._CData'>, <type 'object'>), <attribute 'raw' of 'c_char_Array_16' objects>, <attribute 'value' of 'c_char_Array_16' objects>, (<type '_ctypes.Array'>,), {'raw': <attribute 'raw' of 'c_char_Array_16' objects>, '__module__': 'ctypes', '__dict__': <attribute '__dict__' of 'c_char_Array_16' objects>, '__weakref__': <attribute '__weakref__' of 'c_char_Array_16' objects>, '_length_': 16, '_type_': <class 'ctypes.c_char'>, '__doc__': None, 'value': <attribute 'value' of 'c_char_Array_16' objects>}, <class 'ctypes.c_char_Array_16'>, <attribute '__dict__' of 'c_char_Array_16' objects>, <attribute '__weakref__' of 'c_char_Array_16' objects>, (<class 'ctypes.c_char_Array_16'>, <type '_ctypes.Array'>, <type '_ctypes._CData'>, <type 'object'>), <attribute 'raw' of 'c_char_Array_16' objects>, <attribute 'value' of 'c_char_Array_16' objects>, (<type '_ctypes.Array'>,), {'raw': <attribute 'raw' of 'c_char_Array_16' objects>, '__module__': 'ctypes', '__dict__': <attribute '__dict__' of 'c_char_Array_16' objects>, '__weakref__': <attribute '__weakref__' of 'c_char_Array_16' objects>, '_length_': 16, '_type_': <class 'ctypes.c_char'>, '__doc__': None, 'value': <attribute 'value' of 'c_char_Array_16' objects>}, <class 'ctypes.c_char_Array_16'>, <attribute '__dict__' of 'c_char_Array_16' objects>, <attribute '__weakref__' of 'c_char_Array_16' objects>, (<class 'ctypes.c_char_Array_16'>, <type '_ctypes.Array'>, <type '_ctypes._CData'>, <type 'object'>), <attribute 'raw' of 'c_char_Array_16' objects>, <attribute 'value' of 'c_char_Array_16' objects>, (<type '_ctypes.Array'>,), {'raw': <attribute 'raw' of 'c_char_Array_16' objects>, '__module__': 'ctypes', '__dict__': <attribute '__dict__' of 'c_char_Array_16' objects>, '__weakref__': <attribute '__weakref__' of 'c_char_Array_16' objects>, '_length_': 16, '_type_': <class 'ctypes.c_char'>, '__doc__': None, 'value': <attribute 'value' of 'c_char_Array_16' objects>}, <class 'ctypes.c_char_Array_16'>, <attribute '__dict__' of 'c_char_Array_16' objects>, <attribute '__weakref__' of 'c_char_Array_16' objects>, (<class 'ctypes.c_char_Array_16'>, <type '_ctypes.Array'>, <type '_ctypes._CData'>, <type 'object'>), <attribute 'raw' of 'c_char_Array_16' objects>, <attribute 'value' of 'c_char_Array_16' objects>]
msg210322 - (view) Author: Gustavo J. A. M. Carneiro (gustavo) * Date: 2014-02-05 14:58
I have narrowed it down to one line of code: ctypes.create_string_buffer(16) That is enough to create 7 objects that have reference cycles. [<class 'ctypes.c_char_Array_16'>, {'__module__': 'ctypes', '__doc__': None, '__weakref__': <attribute '__weakref__' of 'c_char_Array_16' objects>, 'raw': <attribute 'raw' of 'c_char_Array_16' objects>, '_length_': 16, '_type_': <class 'ctypes.c_char'>, 'value': <attribute 'value' of 'c_char_Array_16' objects>, '__dict__': <attribute '__dict__' of 'c_char_Array_16' objects>}, (<class 'ctypes.c_char_Array_16'>, <class '_ctypes.Array'>, <class '_ctypes._CData'>, <class 'object'>), <attribute '__weakref__' of 'c_char_Array_16' objects>, <attribute 'raw' of 'c_char_Array_16' objects>, <attribute 'value' of 'c_char_Array_16' objects>, <attribute '__dict__' of 'c_char_Array_16' objects>] So maybe the bug is in ctypes itself, not the uuid module.
msg210328 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2014-02-05 15:44
Yes, I was pretty sure it was in cytpes, from looking at the UUID code.
msg210331 - (view) Author: Gustavo J. A. M. Carneiro (gustavo) * Date: 2014-02-05 16:16
Regardless, if you don't mind, take this patch for Python 3.5 to avoid ctypes, at least in the Linux case (I don't have Windows to test). Creating a proper extension module is safer and really not that hard...
msg210335 - (view) Author: R. David Murray (r.david.murray) * (Python committer) Date: 2014-02-05 16:57
Thanks. This looks like a good idea, but I'll leave it to someone with more experience with this module to review it. Let's change this issue to an enhancement request for uuid instead. If someone wants to work on the cycle-in-ctypes problem they can open a new issue.
msg210346 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2014-02-05 20:08
See also .
msg251509 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2015-09-24 11:38
In the Python stdlib, we try to avoid ctypes to use instead a C extension module. So I like the idea of a new optional _uuid module. I reviewed the attached patch.
msg251510 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2015-09-24 11:38
@Gustavo: Can you please take my remarks in account and rebase your change on the default branch?
msg253493 - (view) Author: Gustavo J. A. M. Carneiro (gustavo) * Date: 2015-10-26 19:14
This patch fixes the Mac OS X issue @haypo pointed out.
msg253494 - (view) Author: Gustavo J. A. M. Carneiro (gustavo) * Date: 2015-10-26 19:25
One issue of note is regarding generate_time(). Originally I found ctypes bindings for this function, so I wrapped it as well in the extension module. However, it doesn't appear to be used...
msg253511 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2015-10-27 02:35
New review (question for Windows).
msg253598 - (view) Author: Gustavo J. A. M. Carneiro (gustavo) * Date: 2015-10-28 13:36
New patch that: 1. adds assert(sizeof(uuid_t) == 16); to the extension module; 2. fixes the code path when ctypes has to be used instead of the extension module (needed a bit more refactoring, apologies if it makes the diff harder to read); 3. Adjusts the uuid module tests to account for the possibility of ctypes not being imported.
msg303219 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2017-09-28 11:18
https://github.com/python/cpython/pull/3796 updates the patch for 3.7 and improves on it a bit by making initialization lazy.
msg303233 - (view) Author: STINNER Victor (vstinner) * (Python committer) Date: 2017-09-28 13:29
There are too many uuid open issues proposing similar changes. I mark this issue as a duplicate of bpo-11063 to avoid splitted discussions. Please continue the discussion there!
msg303280 - (view) Author: Antoine Pitrou (pitrou) * (Python committer) Date: 2017-09-28 21:03
New changeset a106aec2ed6ba171838ca7e6ba43c4e722bbecd1 by Antoine Pitrou in branch 'master': bpo-11063, bpo-20519: avoid ctypes and improve import time for uuid (#3796) https://github.com/python/cpython/commit/a106aec2ed6ba171838ca7e6ba43c4e722bbecd1
History
Date User Action Args
2022-04-11 14:57:58 admin set github: 64718
2017-09-28 21:03:08 pitrou set messages: +
2017-09-28 13:29:10 vstinner set status: open -> closedsuperseder: Rework uuid module: lazy initialization and add a new C extensionmessages: + resolution: duplicatestage: patch review -> resolved
2017-09-28 11🔞33 pitrou set nosy: + pitroumessages: +
2017-09-28 11:17:07 pitrou set versions: + Python 3.7, - Python 3.5
2017-09-28 10:37:57 pitrou set pull_requests: + <pull%5Frequest3781>
2015-10-28 13:36:07 gustavo set files: + uuid.diffmessages: +
2015-10-27 02:35:24 vstinner set messages: +
2015-10-26 19:25:11 gustavo set messages: +
2015-10-26 19:14:38 gustavo set files: + issue20519_10941v2.diffmessages: +
2015-09-24 11:38:45 vstinner set messages: +
2015-09-24 11:38:18 vstinner set messages: +
2015-09-22 21:44:54 vstinner set nosy: + vstinner
2014-02-05 20:08:35 serhiy.storchaka set messages: +
2014-02-05 16:57:23 r.david.murray set versions: + Python 3.5, - Python 2.7, Python 3.3, Python 3.4type: resource usage -> enhancementnosy: + ned.deily, serhiy.storchakatitle: ctypes.create_string_buffer creates reference cycles -> Replace uuid ctypes usage with an extension module.messages: + stage: patch review
2014-02-05 16:16:56 gustavo set files: + uuid-no-ctypes.diffkeywords: + patchmessages: +
2014-02-05 15:44:17 r.david.murray set title: uuid.uuid4().hex generates garbage when ctypes available -> ctypes.create_string_buffer creates reference cyclesnosy: + amaury.forgeotdarc, belopolsky, meador.ingemessages: + components: + ctypes, - Library (Lib)
2014-02-05 14:58:29 gustavo set messages: +
2014-02-05 14:28:22 gustavo set messages: +
2014-02-05 14:10:44 r.david.murray set nosy: + r.david.murraymessages: +
2014-02-05 11:52:23 gustavo create