Tcl Source Code

View Ticket
Login
Ticket UUID: 1869989
Title: memory leak when using expr
Type: Bug Version: obsolete: 8.5.0
Submitter: melbardis Created on: 2008-01-12 16:45:13
Subsystem: 47. Bytecode Compiler Assigned To: msofer
Priority: 9 Immediate Severity:
Status: Closed Last Modified: 2008-01-17 02:49:21
Resolution: Fixed Closed By: msofer
    Closed on: 2008-01-16 19:49:21
Description:
using [expr ...] in a loop appears to cause a constant memory leak. it appears to be allocating stuff in TclLiterla... also fairly (very) slow operation!

tcl 8.5 / windows xp

here is the code i used

#-----------------------------
set numgen 200000
set delta 1
set start_time 1

for {set i 0} {$i < $numgen} {incr i} {

    set time [expr $start_time + ($delta * $i) ]
}
#-----------------------------

memory start small, now it is about 48K and is still running! like i said slow...
User Comments: msofer added on 2008-01-17 02:49:21:
Logged In: YES 
user_id=148712
Originator: NO

Patch reviewed, approved, committed.

dgp added on 2008-01-17 02:11:23:

File Added - 262488: 1869989.patch

Logged In: YES 
user_id=80530
Originator: NO


Here's a patch that removes the 
unbalanced TclCreateLiteral() calls
that caused the memleak.

Might be interesting to see
if tclbench notices anything
significantly different after
applying this patch.

File Added: 1869989.patch

dgp added on 2008-01-16 02:53:45:
Logged In: YES 
user_id=80530
Originator: NO


I would expect the same TclReleaseLiteral
flaws to cause this script to leak:

while 1 {
proc demo {} "set ::var val[incr ::i]"
demo
}

But that doesn't appear to be the case.

dgp added on 2008-01-16 02:41:56:
Logged In: YES 
user_id=80530
Originator: NO


I was mistaken to assume that literal lifetimes
were meant to be permanent.  There is in fact
a conflict in literal lifetime management for
those literals in constant (sub-)expressions.
Diagnosis of memory leak was correct after all.

melbardis added on 2008-01-16 00:04:54:
Logged In: YES 
user_id=788816
Originator: YES

thanks for the explaination

i guess i should of read the documentation a little better :)


eric

dgp added on 2008-01-16 00:00:11:
Logged In: YES 
user_id=80530
Originator: NO


1) No limit.  Yes, over time a program that creates many
   literals can grow in memory footprint.  This is nothing new.

2) The fundamental reason is that you have failed to brace
   the expression.  This means every evaluation of [expr]
   is creating an expression string, parsing that expression
   string (which creates literals), and only then compiling
   and executing the bytecode.  A properly braced expression
   would parse and compile only one time, and let the changing
   contents of a variable produce changing expression results
   when executing the same bytecode again and again.
   Using [+] is more like a braced expression than an unbraced
   expression.  For this example, they produce (nearly?) the
   same bytecode.

Although there's no bug here, it does raise the general question
of literal lifetime which might be worth looking into.

melbardis added on 2008-01-15 22:51:14:
Logged In: YES 
user_id=788816
Originator: YES

it was the literal table growing that was of concern. 

1) is there an upper limit to number of literals allocated? if not then this would have adverse efects on long running server apps that use this construct.

2) why the difference between [expr ..] and the alternative [+ ...] ?

regards
eric

dgp added on 2008-01-15 13:51:05:
Logged In: YES 
user_id=80530
Originator: NO


Perhaps you are not seeing an
actual leak, but just watching
memory consumption grow as the
accumulated parses allocate space
for all the literal values they see?
By the time you are done, the values
"1", "2", ... "200000" will all be
stored in the literal table.  The
same thing should happen in 8.4.

dgp added on 2008-01-15 13:31:01:
Logged In: YES 
user_id=80530
Originator: NO


What is your evidence of a memory leak?

Your original script runs in about
3 seconds for me on a linux system.
Doesn't seem "very" slow considering
you're demanding that it reparse the
expression and all numbers 200000 times.

Of course bracing the expression will
solve that, if it is speed rather than
demonstrating a leak which is at issue.

[email protected] added on 2008-01-12 23:51:26:
Logged In: NO 

i modified the test to use the opreator syntax as such:

#------------------------------
namespace path {::tcl::mathop ::tcl::mathfunc}


set numgen 200000
set delta 1
set start_time 1

for {set i 0} {$i < $numgen} {incr i} {

    #set time [expr $start_time + ($delta * $i) ]
    set time [+ $start_time  [* $delta  $i]]
}

#----------------------------------

almost instant!

Attachments: