My app collects a bunch of data from a SQLite database then runs a
query and plots a chart.
Then it clears the chart with the $::chart delete "all" canvas
command.
Then it runs another query and plots the chart again.
Rinse and repeat over and over. It's a loop.
After about 10 queries give or take, it crashes:
terminated by signal SIGKILL (Forced quit)
I've run it many times and it never gets past the 11th run.
Any idea why this is happening?
My app collects a bunch of data from a SQLite database then runs a query
and plots a chart.
Then it clears the chart with the $::chart delete "all" canvas command.
Then it runs another query and plots the chart again.
Rinse and repeat over and over. It's a loop.
After about 10 queries give or take, it crashes:
terminated by signal SIGKILL (Forced quit)
I've run it many times and it never gets past the 11th run.
Any idea why this is happening?
One possibility, is the app's memory usage growing dramatically, such
that the Linux OOM killer (OOM = Out Of Memory) is activating and
killing it? Although I don't know if the OOM killer sends a SIGKILL.
I don't believe SIGKILL is generated by any error condition. It is a
signal sent with the kill command (or something simular). Is there some monitoring process that is "killing" processes that excede some usage
limit?
On Fri, 23 Dec 2022 16:52:36 -0000 (UTC), Rich wrote:
One possibility, is the app's memory usage growing dramatically, such
that the Linux OOM killer (OOM = Out Of Memory) is activating and
killing it? Although I don't know if the OOM killer sends a SIGKILL.
You are probably right. I am watching the output of 'free -m' and I see
the amount of free memory does drop steadily until it is around 100MB,
then the Tcl application crashes.
Is there anything I can do to prevent that? Some kind of 'flush memory' command or hack? I am trying to unset all variables I can without breaking the app completely at the end of every loop iteration, but that is not solving the problem.
On Fri, 23 Dec 2022 17:06:27 +0000, Robert Heller wrote:
I don't believe SIGKILL is generated by any error condition. It is a signal sent with the kill command (or something simular). Is there some monitoring process that is "killing" processes that excede some usage limit?
Maybe. I never put it there myself, but maybe Debian has some such
mechanism built in.
On Fri, 23 Dec 2022 16:52:36 -0000 (UTC), Rich wrote:
One possibility, is the app's memory usage growing dramatically, such
that the Linux OOM killer (OOM = Out Of Memory) is activating and
killing it? Although I don't know if the OOM killer sends a SIGKILL.
You are probably right. I am watching the output of 'free -m' and I see
the amount of free memory does drop steadily until it is around 100MB,
then the Tcl application crashes.
Is there anything I can do to prevent that?
Some kind of 'flush memory' command or hack? I am trying to unset
all variables I can without breaking the app completely at the end of
every loop iteration, but that is not solving the problem.
On Fri, 23 Dec 2022 17:06:27 +0000, Robert Heller wrote:
I don't believe SIGKILL is generated by any error condition. It is
a signal sent with the kill command (or something simular). Is
there some monitoring process that is "killing" processes that
excede some usage limit?
Maybe. I never put it there myself, but maybe Debian has some such
mechanism built in.
You say are doing SQL queries -- what package are you using to do that?
Also, are you acclumulating results in memory? Maybe you should not do
that.
On Fri, 23 Dec 2022 18:38:33 +0000, Robert Heller wrote:
You say are doing SQL queries -- what package are you using to do that?
set ::dbfile "$::BASEDIR/somefile.db"
set ::sqllibrary "$::BASEDIR/libtclsqlite3.so"
load $::sqllibrary
sqlite3 sql $::dbfile -nomutex 1
Also, are you acclumulating results in memory? Maybe you should not do
that.
I thought about that, but I've been doing some debugging:
foreach i [info vars] {
if {[array exists $i]} {
rw a /dev/shm/allvars.txt "$i [array size $i]\n"
} else {
rw a /dev/shm/allvars.txt "$i [strlen [set $i]]\n"
}
}
Nothing seems to be growing horribly. Pretty modest numbers actually.
I noticed two interesting things:
1) There is a text widget that gets updated at every iteration.
$textbox delete 1.0 end
$textbox insert end "some data"
Disabling that text widget makes the free available memory drop
more slowly. Not much, but certainly noticeable.
2) I've found that destroying the entire parent window and recreating everything in it on every iteration makes a big difference. The
memory still drops, but a lot slower. Still drops though. Slow but
sure. That puts a limit on the number of iterations I can run.
That's bad news.
set ::dbfile "$::BASEDIR/somefile.db"
set ::sqllibrary "$::BASEDIR/libtclsqlite3.so"
load $::sqllibrary
Why are you doing this above instead of "package require sqlite3"?
sqlite3 sql $::dbfile -nomutex 1
How are you doing your queries?
I thought about that, but I've been doing some debugging:
foreach i [info vars] {
if {[array exists $i]} {
rw a /dev/shm/allvars.txt "$i [array size $i]\n"
} else {
rw a /dev/shm/allvars.txt "$i [strlen [set $i]]\n"
}
}
What is "rw a"???
How big does that file become? Because it is also eating up memory
(/dev/shm is the Linux ramdisk, which uses RAM to store its contents).
The 'delete 1.0 end' should make the text widget memory usage not grow forever.
In your original post you were doing something with graphs. Does the
graph library include a "delete/free/destroy" call that you are
missing?
On Fri, 23 Dec 2022 19:21:26 -0000 (UTC), Rich wrote:
set ::dbfile "$::BASEDIR/somefile.db"
set ::sqllibrary "$::BASEDIR/libtclsqlite3.so"
load $::sqllibrary
Why are you doing this above instead of "package require sqlite3"?
So what is wrong with using the .so library? Is it bad? Why? What are
the undesired side effects?
On Fri, 23 Dec 2022 19:21:26 -0000 (UTC), Rich wrote:
set ::dbfile "$::BASEDIR/somefile.db"
set ::sqllibrary "$::BASEDIR/libtclsqlite3.so"
load $::sqllibrary
Why are you doing this above instead of "package require sqlite3"?
I like that approach because I can bundle the .so library with the applications I intend to share when they're ready.
Including a package is less simple and lots of people may not have
the package.
So what is wrong with using the .so library? Is it bad? Why? What are
the undesired side effects?
sqlite3 sql $::dbfile -nomutex 1
How are you doing your queries?
All according to this page:
https://www.sqlite.org/tclsqlite.html
foreach i [info vars] {
if {[array exists $i]} {
rw a /dev/shm/allvars.txt "$i [array size $i]\n"
} else {
rw a /dev/shm/allvars.txt "$i [strlen [set $i]]\n"
}
}
What is "rw a"???
rw is a proc that reads or writes to files. "rw a" is write/append.
That piece of code above was introduced later, to investigate the
problem that was observed before the code was introduced.
That piece of code above was introduced later, to investigate the
problem that was observed before the code was introduced.
The 'delete 1.0 end' should make the text widget memory usage not grow
forever.
Well, yes, and it keeps the content visible too. Without it, the text
widget would scroll so far down it could possibly find oil.
In your original post you were doing something with graphs. Does
the graph library include a "delete/free/destroy" call that you are
missing?
My graph library is Tk and canvas. No third-party library whatsoever.
Is it reasonable that I have to destroy and recreate the entire GUI
at every iteration so the application remains barely stable?
The chart is far from being visually intense or busy. It's quite simple.
Why is it eating so much memory?
Is there some "best practice" I am overlooking here to avoid that
kind of pitfall?
Do you draw a new graph for each iteration?
If yes, do you delete all the old graphs objects first? If not, your
memory growth could also be an accumulation of undeleted canvas
objects.
Also, for modern Tcl (i.e., 8.6+) Sqlilte3 is included as part of the
base Tcl install, so at least for sqlite, a "package require sqlite3"
should always succeed, provided someone has Tcl itself properly
installed.
See if you can trim down to a minimal version that still 'leaks' --
then stop being so secretive and reveal that minimal version here.
Note also that trying to "trim down" can often reveal the cause,
because as you trim, if you suddenly have no more leak, then the last
thing you trimmed was likely the cause. So trim down in small
increments.
On Sat, 24 Dec 2022 12:56:42 -0000 (UTC), Rich wrote:
Do you draw a new graph for each iteration?
If yes, do you delete all the old graphs objects first? If not, your
memory growth could also be an accumulation of undeleted canvas
objects.
Yes and yes. Like I said previously,
"My app collects a bunch of data from a SQLite database then runs a query
and plots a chart.
Then it clears the chart with the $::chart delete "all" canvas command.
Then it runs another query and plots the chart again. Rinse and repeat
over and over. It's a loop."
Also, for modern Tcl (i.e., 8.6+) Sqlilte3 is included as part of
the base Tcl install, so at least for sqlite, a "package require
sqlite3" should always succeed, provided someone has Tcl itself
properly installed.
I reject this whole idea of a "modern Tcl." Not everybody can afford to
have the latest and greatest. If I were coding for Windows, I would be
trying to support Windows 95. I hate this idea of excluding perfectly
capable old machines or environments.
See if you can trim down to a minimal version that still 'leaks' --
then stop being so secretive and reveal that minimal version here.
Note also that trying to "trim down" can often reveal the cause,
because as you trim, if you suddenly have no more leak, then the
last thing you trimmed was likely the cause. So trim down in small
increments.
Yes, I will do that. Later on. I'm taking a break now for a couple
of days. Thank you for the help and Merry Christmas!
Luc <[email protected]> wrote:
On Sat, 24 Dec 2022 12:56:42 -0000 (UTC), Rich wrote:
Do you draw a new graph for each iteration?
If yes, do you delete all the old graphs objects first? If not, your
memory growth could also be an accumulation of undeleted canvas
objects.
Yes and yes. Like I said previously,
"My app collects a bunch of data from a SQLite database then runs a query
and plots a chart.
Then it clears the chart with the $::chart delete "all" canvas command.
Then it runs another query and plots the chart again. Rinse and repeat
over and over. It's a loop."
Ok, unless the canvas contains a leak under the hood (i.e., a bug) that should clean up all memory allocated by canvas objects.
I lump that together with the idea of making sure my apps will run on older versions of Linux and Tcl. I don't want to have the latest and greatest Tcl. Because people who decide to use my apps may not have the so much latest
and greatest. So ideally, I should be using Tcl/Tk 8.5 to test my apps.
I should write code that is likely to run on both old and new versions.
I want the "Runs on Woody" certification.
I could even go with 8.4, except that I really like the argument expansion nipple...
"My app collects a bunch of data from a SQLite database then runs a query
and plots a chart.
Then it clears the chart with the $::chart delete "all" canvas command.
Then it runs another query and plots the chart again. Rinse and repeat
over and over. It's a loop."
| Sysop: | Keyop |
|---|---|
| Location: | Huddersfield, West Yorkshire, UK |
| Users: | 715 |
| Nodes: | 16 (2 / 14) |
| Uptime: | 44:47:38 |
| Calls: | 12,111 |
| Calls today: | 2 |
| Files: | 15,010 |
| Messages: | 6,518,463 |