(I like the reset() name. Charles-François suggested this name
inspired by OProfile API.)
> disable() function:
>
> Stop tracing Python memory allocations and clear traces of
> memory blocks allocated by Python.
>
> I would disable to stop tracing, but I would not expect it to clear
> out the traces it had already captured. If it has to do that, please
> put in some sample code showing how to save the current traces before
> disabling.
For consistency, you cannot keep traces when tracing is disabled. The
free() must be enabled to remove allocated memory blocks, or next
malloc() may get the same address which would raise an assertion error
(you cannot have two memory blocks at the same address).
Just call get_traces() to get traces before clearing them. I can
explain it in the doc.
2013/10/29 Kristján Valur Jónsson <kris...@ccpgames.com>:
> I was thinking something similar. It would be useful to be able to "pause" and "resume"
> if one is doing any analysis work in the live environment. This would reduce the
> need to have "Filter" objects.
For the reason explained above, it's not possible to disable the whole
module temporarly.
Internally, tracemalloc uses a thread-local variable (called the
"reentrant" flag) to disable temporarly tracing allocations in the
current thread. It only disables tracing new allocations,
deallocations are still proceed.
Victor
> 2013/10/29 Jim Jewett <jimjj...@gmail.com>:
> > reset() function:
> >
> > Clear traces of memory blocks allocated by Python.
> >
> > Does this do anything besides clear? If not, why not just re-use the
> > 'clear' name from dicts?
>
> (I like the reset() name. Charles-François suggested this name
> inspired by OProfile API.)
Just "reset" implies to me that you're ready to start over. Not just
traced memory blocks but accumulated statistics and any configuration
(such as Filters) would also be reset. Also tracing would be disabled
until started explicitly.
If you want it to apply just to the traces, reset_traces() would be
more appropriate.
> > disable() function:
> >
> > Stop tracing Python memory allocations and clear traces of
> > memory blocks allocated by Python.
> >
> > I would disable to stop tracing, but I would not expect it to clear
> > out the traces it had already captured. If it has to do that, please
> > put in some sample code showing how to save the current traces before
> > disabling.
>
> For consistency, you cannot keep traces when tracing is disabled. The
> free() must be enabled to remove allocated memory blocks, or next
> malloc() may get the same address which would raise an assertion error
> (you cannot have two memory blocks at the same address).
Then I would not call this "disable". disable() should not "destroy" data.
> Just call get_traces() to get traces before clearing them. I can
> explain it in the doc.
Shouldn't disable() do this automatically, perhaps with an optional
discard_traces flag (which would be False by default)?
But I definitely agree with Jim: You *must* provide an example here
showing how to save the traces (even though it's trivial to do so),
because that will make clear that disable() is a destructive
operation. (It is not destructive in any other debugging tool that
I've used.) Even with documentation, be prepared for user complaints.
Le 30 oct. 2013 20:58, "Jim Jewett" <jimjj...@gmail.com> a écrit :
> hough if you use a dict internally, that might not
> be the case.
Tracemalloc uses a {address: trace} duct internally.
> If you return it as a list instead of a dict, but that list is
> NOT in time-order, that is worth documenting
Ok i will document it.
> Also, am I misreading the documentation of get_traces() function?
>
> Get traces of memory blocks allocated by Python.
> Return a list of (size: int, traceback: tuple) tuples.
> traceback is a tuple of (filename: str, lineno: int) tuples.
>
>
> So it now sounds like you don't bother to emit de-allocation
> events because you just remove the allocation from your
> internal data structure.
I don't understand your question. Tracemalloc does not store events but traces. When a memory block is deallocated, it us removed from the internal dict (and so from get_traces() list).
> I still don't see anything here(*) that requires even saving
> the address, let alone preventing re-use.
The address must be stored internally to maintain the internal dict. See the C code.
> (1) Whoa -- memory hog! How can I fix this?
>
> (2) I know -- track allocallocations, with a traceback showing why they
> were made. (At a minimum, I would like to be able to subclass your
> tool to do this -- preferably without also keeping the full history in
> memory.)
What do you mean by "full history" and "subclass your tool"?
> (3) Oh, maybe I should skip the ones that really are temporary and
> get cleaned up. (You make this easy by handling the de-allocs,
> though I'm not sure those events get exposed to anyone working at
> the python level, as opposed to modifying and re-compiling.)
If your temporary objects are destroyed before you call get_traces(), you will not see them in get_traces(). I don't understand.
> (4) hmm... still too big ... I should use filters. (But will changing those
> filters while tracing is enabled mess up your current implementation?)
If you call add_filter(), new traces() will be filtered. Not the old ones, as explained in the doc. What do you mean by "mess up"?
> (5) Argh. What I really want is to know what gets allocated at times
> like XXX.
> I can do that if times-like-XXX only ever occur once per process. I *might* be
> able to do it with filters. But I would rather do it by saying "trace on" and
> "trace off". Maybe even with a context manager around the suspicious
> places.
I don't understand "times like XXX", what is it?
To see what happened between two lines of code, you can compare two snapshots. No need to disable tracing.
> (6) Then, at the end of the run, I would say "give me the info about how much
> was allocated when tracing was on." Some of that might be going away
> again when tracing is off, but at least I know what is making the allocations
> in the first place. And I know that they're sticking around "long enough".
I think you musunderstood how tracemalloc works. You should compile it and play with it. In my opinion, you already have everything in tracemalloc for you scenario.
> Under your current proposal, step (5) turns into
>
> set filters
> trace on
> ...
> get_traces
> serialize to some other storage
> trace off
s1=take_snapshot()
...
s2=take_snapshot()
...
diff=s2.statistics("lines", compare_to=s1)
> why even have
> get_traces,
> as opposed to just take_snapshot? Is there some difference between them,
> except that a snapshot has some convenience methods and some simple
> metadata?
See the doc: Snapshot.traces is the result of get_traces().
get_traces() is here is you want to write your own tool without Snapshot.
Victor
If I give access to this flag, it would be possible to disable
temporarily tracing in the current thread, but tracing would still be
enabled in other threads. Would it fit your requirement?
Example:
---------------
tracemalloc.enable()
# start your application
...
# spawn many threads
...
# oh no, I don't want to trace this ugly function
tracemalloc.disable_local()
ugly_function()
tracemalloc.enable_local()
...
snapshot = take_snapshot()
---------------
You can imagine a context manager based on these two functions:
---------------
with disable_tracing_temporarily_in_current_thread():
ugly_function()
---------------
I still don't understand why you would need to stop tracing
temporarily. When I use tracemalloc, I never disable it.