Euphoria Ticket #149: memory leak

I have a EUPHORIA program that leaks memory. It's runs events based on a timer system every 800 milliseconds. The program isn't continuously collecting data into a sequence.

I suspect this can be demonstrated by any program that calls subroutines as frequently. This could be caused by unbalanced referencing objects. The program usually uses around 21MB at the beginning and then overtime leaks. I will be running a test with 3040 vs 3145 (with system memory) and post the results here.

Details

Type: Bug Report Severity: Blocking Category: Interpreter
Assigned To: unknown Status: Fixed Reported Release: 3146
Fixed in SVN #: 3198, 3201 View VCS: 3198, 3201 Milestone:

1. Comment by SDPringle Apr 12, 2010

This is the memory usage according to Windows task manager of running a Windows clock program written in EUPHORIA interpreted by versions 3040 and 3145 respectively.

time version memory starting... 09:48 3040 15 MB 09:48 3145 14 MB

okay Window is up and going through winMain... 09:49 3040 23356kB 09:49 3145 21184kB 09:54 3040 23372kB 09:54 3145 21436kB 10:03 3040 23572kB 10:03 3145 21544kB 10:11 3040 23572kB 10:11 3145 21728kB 10:52 3040 43820kB 10:52 3145 39296kB

2. Comment by mattlewis Apr 12, 2010

Can you tell us what the program is? There's nothing here that anyone other than you can do about this.

3. Comment by mattlewis Apr 12, 2010

Converted Shawn's data to table:

Time r3040 r3145
09:49 23,356kB 21,184kB
09:54 23,372kB 21,436kB
10:03 23,572kB 21,544kB
10:11 23,572kB 21,728kB
10:52 43,820kB 39,296kB

4. Comment by mattlewis Apr 12, 2010

Ouch...this page needs some table stylin' love. Added extra columns for better legibility:

Time ... r3040 ... r3145
09:49 23,356kB 21,184kB
09:54 23,372kB 21,436kB
10:03 23,572kB 21,544kB
10:11 23,572kB 21,728kB
10:52 43,820kB 39,296kB


Well, looks like we've plugged something since r3040.

5. Comment by SDPringle Apr 13, 2010

The program is closed source. I'll try to reproduce it with some other program....

memusetest.exw

starts at 18136k and goes up include Win32Lib.ew include std/machine.e include std/win32/msgbox.e constant TheWindow = createEx( Window, "The Window", 0, 0, 0, 100, 100, 0, 0 ) constant CleanFace = create( Pixmap, "", TheWindow, 0, 0, 100, 100, WS_VISIBLE ) constant ClockFace = create( Pixmap, "", TheWindow, 0, 0, 100, 100, WS_VISIBLE )

integer counter counter = 0 sequence mem procedure TheWindow_onTimer (integer self, integer event, sequence params)params is ( int timerId) counter = counter + 1 printf(1,"Timer rang %d!\n", {counter} ) copyBlt(ClockFace, 0,0, CleanFace ) copyBlt(TheWindow, 0,0,ClockFace) ifdef SAFE then if compare( mem, { machine:memory_used(), machine:allocations() } ) != 0 then puts(1, "There has been a change in memory.") abort(0) end if end ifdef end procedure setHandler( TheWindow, w32HTimer, routine_id("TheWindow_onTimer")) mem = { machine:memory_used(), machine:allocations() } setTimer( TheWindow, 0, 10 ) WinMain(TheWindow, Normal) ifdef SAFE then message_box( machine:info(), "Memory Information", MB_OK ) end ifdef

Now add the following to safe.e:

public function info() integer tm = 0 for i = 1 to length( safe_address_list ) do tm += safe_address_list[i][BLOCK_LENGTH] end for return sprintf(""" Total memory allocations %10d Total memory allocated %10dB""", { length(safe_address_list), tm } ) end function

public function memory_used() integer tm = 0 for i = 1 to length( safe_address_list ) do tm += safe_address_list[i][BLOCK_LENGTH] end for return tm end function

public function allocations() return length( safe_address_list ) end function

now run with the -D SAFE option. Run this program for ten minutes and record the memory used in the task manager. Then do it again an hour after that and you should see some difference.

6. Comment by SDPringle Apr 13, 2010

With the last test, I compiled EUPHORIA with all of the defaults configure gives you: Managed memory, no debug and no checking options. My ticket addition didn't come out well. I should preview first...

Let's try that again:

Add this to safe.e:

public function info() 
	integer tm = 0 
	for i = 1 to length( safe_address_list ) do 
		tm += safe_address_list[i][BLOCK_LENGTH] 
	end for 
	return sprintf(""" 

Total memory allocations %10d 
Total memory allocated   %10dB""", 
	{ length(safe_address_list), tm } ) 
end function 
 
public function memory_used() 
	integer tm = 0 
	for i = 1 to length( safe_address_list ) do 
		tm += safe_address_list[i][BLOCK_LENGTH] 
	end for 
	return tm 
end function 
 
public function allocations() 
	return length( safe_address_list ) 
end function 

Run memusagetest.exw with -D SAFE. Here is the text of memusagetest.exw:

--starts at 18136k and goes up 
include Win32Lib.ew 
include std/machine.e 
include std/win32/msgbox.e 
constant TheWindow = createEx( Window, "The Window", 0, 0, 0, 100, 100, 0, 0 ) 
constant CleanFace = create( Pixmap, "", TheWindow, 0, 0, 100, 100, WS_VISIBLE ) 
constant ClockFace = create( Pixmap, "", TheWindow, 0, 0, 100, 100, WS_VISIBLE ) 
 
integer counter 
counter = 0 
sequence mem 
procedure TheWindow_onTimer (integer self, integer event, sequence params)--params is ( int timerId) 
	counter = counter + 1 
	printf(1,"Timer rang %d!\n", {counter} ) 
	copyBlt(ClockFace, 0,0, CleanFace ) 
	copyBlt(TheWindow, 0,0,ClockFace) 
	ifdef SAFE then 
	    if compare( mem, { machine:memory_used(), machine:allocations() } ) != 0 then 
		    puts(1, "There has been a change in memory.") 
		    abort(0) 
	    end if	 
	end ifdef 
end procedure 
setHandler( TheWindow, w32HTimer, routine_id("TheWindow_onTimer")) 
mem = { machine:memory_used(), machine:allocations() } 
setTimer( TheWindow, 0, 10 ) 
WinMain(TheWindow, Normal) 
ifdef SAFE then 
    message_box( machine:info(), "Memory Information", MB_OK ) 
end ifdef 

7. Comment by LarryMiller Apr 29, 2010

This program also leaks memory:

include std/text.e 
 
sequence void 
while 1 do 
	void=upper("aaaaaaaaaaaaaa") 
	for i=1 to 10000 do 
	end for 
end while 

I don't see anything wrong in the upper() function so I suspect the problem is in the interpreter.

8. Comment by mattlewis Apr 29, 2010

Larry, which platform?

9. Comment by jimcbrown Apr 29, 2010

I've never seen Larry use Linux or any other kind of Unix.

10. Comment by mattlewis Apr 29, 2010

I was kinda hoping for that, since the windows version of upper uses C calls to windows. I'm thinking that the leak has to do with c calls and/or callbacks, though I haven't nailed it down yet.

11. Comment by LarryMiller Apr 29, 2010

I should have mentioned, I am using XP. I have an application in development that has a serious memory leak that I have not been able to locate. I eventually found that a call to upper() was at least a major contributor to the problem.

12. Comment by mattlewis May 02, 2010

I found and fixed a memory leak in svn:3198. I'm not sure that it's what was causing the problems here, however. The problem was not cleaning up temps created by sequences:

c_proc( foo, { bar, baz } ) 

The sequence passed to c_proc wouldn't be cleaned up properly. I'm not convinced that this would cause a large memory leak, since the next time the same code was executed, the temp should be cleaned up during its assignment.

13. Comment by LarryMiller May 03, 2010

Using r3198 I get the same results as before.

14. Comment by RStowasser May 06, 2010

If I do not use the for loop, the memory leak is still more impressive. In Windows Vista I used this code with rev 3200:

include std/text.e 
--include wildcard.e 
  
sequence txt  
while 1 do 
    txt = upper("a") 
--    txt = lower("a") 
--    txt = "a"  -- works 
end while 

I have to hurry to kill euiw.exe with the task manager. Using euc and openWatcom there seems to be no memory leak. If I include wildcard.e this seems to work ok too. So maybe the problem is in std/text.e?

If I leave the include statements away using txt = "a" with euiw.exe this will use 1588 kb of memory. Using wildcard.e will use 1748 kb of memory and applying std/text.e will use 6000 kb. Is this additional ram justified?

15. Comment by jimcbrown May 06, 2010

The fact that std/text.e leaks but wildcard.e works, I think, makes it pretty clear that this is at least a bug in how c funcs are handled.

I strongly suspect that the leak is DEP related.

16. Comment by mattlewis May 07, 2010

Yeah, I've been suspecting either callbacks or c calls, but memory leaks are a real pain in windows, and I haven't been able to reproduce a leak with similar code under linux.

17. Comment by mattlewis May 07, 2010

Try svn:3201. It seems to have fixed the upper() leak, and I suspect it may fix the initial, win32lib leak as well.

The problem was a spurious reference when an inlined function was assigned to a variable instead of a temp.

18. Comment by LarryMiller May 07, 2010

When testing with r3201 I no longer see the leak in the sample I submitted. Early tests with my own application also do not show the memory leak.

Testing on XP.

19. Comment by SPringle May 13, 2010

I am using 3202 and if you hide its window and then show its Window repeatedly in the example left here you will see the memory use going up.

20. Comment by LarryMiller May 15, 2010

After further testing with my app I find that the leak is till present. I cannot be 100% certain that there is not a problem with my code. After translation with euc the leak is much reduced but still present.

I have been using the "VM Size" column in Task Manager with XP. This is the private bytes of the process. This is a more reliable indicator of a leak than "Mem Usage" which refers to physical memory. Physical memory usage is always under the control of the OS and the levels will not be entirely predictable.

I am sure the developers know this but others may not.

21. Comment by DerekParnell Aug 02, 2010

Just asking for an update on this issue.

It seems to me that there is no leak in Euphoria anymore but there might be one in win32lib. Can anyone show me some code that demonstrates a leak in Euphoria? If not, I'll close this issue.

22. Comment by DerekParnell Aug 04, 2010

No longer seems to be a problem.

Search



Quick Links

User menu

Not signed in.

Misc Menu