Hi everybody,
Ever since I first started programming with Pd, I have had a vague anxiety about symbols, or to be more exact, symbol table growth. Now, I've never run into a problem in real life, but the worry is still there, nagging at me, ever since I read on a Pd-list thread that each symbol takes up permanent, un-reclaimable space in a symbol table. So, I've always been wary about employing many symbols, or having some dynamic process that creates many symbols on the fly.
Attached is [maketime], a lovely little timer/stopwatch. I've long since lost track of who made it, so I'm sorry can't give you well-deserved credit here. At any rate, it creates *at least* one symbol per second (probably more, I'm not sure if each [makefilename] generates a new symbol, but I'm guessing it does). This makes me nervous, as I have no idea what the symbol table capacity is, or how to see how "full" it is. It seems likely that this abstraction would crash eventually.
A) Is it true that [maketime] would continually grow the symbol table?
B) Is it possible to tell how full the symbol table is? How much memory is allocated to it in the first place?
C) Wouldn't it be nice to have some truly transient symbols, that could be abstraction-local, or at least, re-usable?
Cheers,
Phil Stone
#N canvas 300 22 311 311 12; #X obj 36 10 cnv 15 220 40 empty *time-display-cnv-in* 0:00:00 20 18 0 36 -1 -241291 0; #X msg 35 235 ; *time-display-cnv-in* label $1; #X obj 69 155 + 1; #X obj 35 154 f; #X obj 35 111 metro 1000; #X msg 133 111 0; #X obj 35 83 tgl 15 0 empty empty empty 0 -6 0 8 -262144 -1 -1 0 1 ; #X floatatom 35 182 5 0 0 0 - - -; #X obj 133 85 loadbang; #N canvas 0 22 450 459 sec-to-time-symbol 0; #X obj 24 17 inlet; #X obj 50 337 outlet; #X msg 84 258 set $1; #X obj 50 312 makefilename not-set-yet; #X floatatom 50 258 0 0 0 0 - - -; #X msg 171 177 set $1; #X obj 84 205 makefilename not-set-yet; #N canvas 0 22 450 300 format 0; #X obj 24 20 inlet; #X obj 24 224 outlet; #X obj 91 105 + 1; #X obj 24 47 t f f; #X obj 24 171 makefilename 0%d; #X obj 176 171 makefilename %d; #X obj 91 80 >= 10; #N canvas 0 22 450 300 gate2 0; #X obj 44 237 spigot; #X obj 44 262 outlet; #X obj 123 238 spigot; #X obj 123 263 outlet; #X obj 21 30 inlet; #X obj 288 38 inlet; #X obj 359 129 loadbang; #X obj 93 194 unpack 0 0; #X obj 288 62 route 0 1 2; #X msg 350 95 0 1; #X msg 319 127 1 0; #X msg 288 166 0 0; #X connect 0 0 1 0; #X connect 2 0 3 0; #X connect 4 0 0 0; #X connect 4 0 2 0; #X connect 5 0 8 0; #X connect 6 0 11 0; #X connect 7 0 0 1; #X connect 7 1 2 1; #X connect 8 0 11 0; #X connect 8 1 10 0; #X connect 8 2 9 0; #X connect 9 0 7 0; #X connect 10 0 7 0; #X connect 11 0 7 0; #X restore 24 133 pd gate2; #X connect 0 0 3 0; #X connect 2 0 7 1; #X connect 3 0 7 0; #X connect 3 1 6 0; #X connect 4 0 1 0; #X connect 5 0 1 0; #X connect 6 0 2 0; #X connect 7 0 4 0; #X connect 7 1 5 0; #X restore 84 177 pd format; #X obj 171 84 % 60; #X obj 85 82 / 60; #X obj 85 115 int; #X obj 84 142 % 60; #X obj 24 115 int; #X obj 24 82 / 3600; #X obj 24 44 t f f f; #X obj 84 234 makefilename %%d:%s; #X obj 171 153 makefilename %%s:%s; #N canvas 0 22 450 300 format 0; #X obj 24 20 inlet; #X obj 24 224 outlet; #X obj 91 105 + 1; #X obj 24 47 t f f; #X obj 24 171 makefilename 0%d; #X obj 176 171 makefilename %d; #X obj 91 80 >= 10; #N canvas 0 22 450 300 gate2 0; #X obj 44 237 spigot; #X obj 44 262 outlet; #X obj 123 238 spigot; #X obj 123 263 outlet; #X obj 21 30 inlet; #X obj 288 38 inlet; #X obj 359 129 loadbang; #X obj 93 194 unpack 0 0; #X obj 288 62 route 0 1 2; #X msg 350 95 0 1; #X msg 319 127 1 0; #X msg 288 166 0 0; #X connect 0 0 1 0; #X connect 2 0 3 0; #X connect 4 0 0 0; #X connect 4 0 2 0; #X connect 5 0 8 0; #X connect 6 0 11 0; #X connect 7 0 0 1; #X connect 7 1 2 1; #X connect 8 0 11 0; #X connect 8 1 10 0; #X connect 8 2 9 0; #X connect 9 0 7 0; #X connect 10 0 7 0; #X connect 11 0 7 0; #X restore 24 133 pd gate2; #X connect 0 0 3 0; #X connect 2 0 7 1; #X connect 3 0 7 0; #X connect 3 1 6 0; #X connect 4 0 1 0; #X connect 5 0 1 0; #X connect 6 0 2 0; #X connect 7 0 4 0; #X connect 7 1 5 0; #X restore 171 116 pd format; #X connect 0 0 14 0; #X connect 2 0 3 0; #X connect 3 0 1 0; #X connect 4 0 3 0; #X connect 5 0 6 0; #X connect 6 0 15 0; #X connect 7 0 6 0; #X connect 8 0 17 0; #X connect 9 0 10 0; #X connect 10 0 11 0; #X connect 11 0 7 0; #X connect 12 0 4 0; #X connect 13 0 12 0; #X connect 14 0 13 0; #X connect 14 1 9 0; #X connect 14 2 8 0; #X connect 15 0 2 0; #X connect 16 0 5 0; #X connect 17 0 16 0; #X restore 35 208 pd sec-to-time-symbol; #X text 176 111 reset time; #X text 57 83 start; #X connect 2 0 3 1; #X connect 3 0 2 0; #X connect 3 0 7 0; #X connect 4 0 3 0; #X connect 5 0 7 0; #X connect 5 0 3 1; #X connect 6 0 4 0; #X connect 7 0 9 0; #X connect 8 0 5 0; #X connect 9 0 1 0;
On Sun, 22 Feb 2009, Phil Stone wrote:
A) Is it true that [maketime] would continually grow the symbol table?
yes.
B) Is it possible to tell how full the symbol table is? How much memory is allocated to it in the first place?
It never gets full. It just becomes bigger and bigger, as long as you have enough RAM. As it gets bigger, symbol-lookup becomes slower, and symbol-generation too as it always involves one symbol-lookup. The lookup time is always O(n). However, in normal circumstances, it's close to n/16384, an extremely small multiple of n, whereas if you're extremely unlucky, it could be just n steps. The symbols are spread out in a large table in a random-looking manner that is not really random. Each slot in the table has a list of symbols which starts being empty and then grows as needed.
If the symbols were organised as a tree, it wouldn't be a theoretical speed problem, but it would still end up eating up RAM.
The table starts at 64k, or 128k in 64-bit mode, and each symbol takes an additional amount of RAM, but it depends on which malloc you use and such.
C) Wouldn't it be nice to have some truly transient symbols, that could be abstraction-local, or at least, re-usable?
yes, but it's nowhere near happening.
_ _ __ ___ _____ ________ _____________ _____________________ ... | Mathieu Bouchard - tél:+1.514.383.3801, Montréal, Québec
Hallo, Phil Stone hat gesagt: // Phil Stone wrote:
Attached is [maketime], a lovely little timer/stopwatch. I've long since lost track of who made it, so I'm sorry can't give you well-deserved credit here. At any rate, it creates *at least* one symbol per second (probably more, I'm not sure if each [makefilename] generates a new symbol, but I'm guessing it does). This makes me nervous, as I have no idea what the symbol table capacity is, or how to see how "full" it is. It seems likely that this abstraction would crash eventually.
A fix for this maketime would be to reuse the symbols ":00" ... ":59" for minutes and hours by using two [cnv] objects for these. Then you would be able to let the clock run for decades before you get into trouble with the symbol table.
Every table or receiver or route-selector etc. also is a symbol. So while the implementation of the symbol table is suboptimal, in practice it's not something you need to worry about too much. At least it should not make you replace [route freq note] with [route 0 1] :-)
Frank
Frank Barknecht wrote:
Hallo, Phil Stone hat gesagt: // Phil Stone wrote:
Attached is [maketime], a lovely little timer/stopwatch. I've long since lost track of who made it, so I'm sorry can't give you well-deserved credit here. At any rate, it creates *at least* one symbol per second (probably more, I'm not sure if each [makefilename] generates a new symbol, but I'm guessing it does). This makes me nervous, as I have no idea what the symbol table capacity is, or how to see how "full" it is. It seems likely that this abstraction would crash eventually.
A fix for this maketime would be to reuse the symbols ":00" ... ":59" for minutes and hours by using two [cnv] objects for these. Then you would be able to let the clock run for decades before you get into trouble with the symbol table.
I've pondered this, and can't figure out what you mean, unless you're suggesting having 60 canvases, one for each possible number?
I did re-work [maketime] a little. Attached is a version (called [ps-stopwatch] that adds some features and only creates one symbol per second (plus one per minute, plus one per hour); the original created six per second. The new one requires zexy's [makesymbol] (which can convert lists of numbers into a single symbol -- perfect for this application, but not in Vanilla-Pd, obviously).
Every table or receiver or route-selector etc. also is a symbol.
Yes, but except in some extreme examples of dynamic programming, this is a known quantity. My anxiety comes from the memory leak behavior of long-running patches that dynamically create symbols (anything that does any sort of string handling is in this category, usually). It would be so much better to have transient symbols for this sort of thing, but as Mathieu said, it sounds like this is not going to happen any time soon.
So while the implementation of the symbol table is suboptimal, in practice it's not something you need to worry about too much. At least it should not make you replace [route freq note] with [route 0 1] :-)
Just to see the magnitude of the issue, I made a little test patch (attached) called [symbol_pig]. It just creates symbols, very fast. A very rough measurement based on watching resident memory increasing in bash's top command indicates that (on OS X 10.4), a megabyte is used up for approximately every 32,000 symbols.
Phil
#N canvas 0 22 450 300 10; #X obj 109 47 metro 10; #X obj 146 80 + 1; #X obj 109 79 f 0; #X obj 109 117 makefilename %d; #X symbolatom 109 148 10 0 0 0 - - -; #X obj 109 23 tgl 15 0 empty empty empty 17 7 0 10 -262144 -1 -1 0 1; #X connect 0 0 2 0; #X connect 1 0 2 1; #X connect 2 0 1 0; #X connect 2 0 3 0; #X connect 3 0 4 0; #X connect 5 0 0 0;
#N canvas 788 73 273 360 12; #X declare -lib zexy; #X obj 1 1 cnv 15 156 30 empty $0-time_display 0:03:36 6 15 0 24 -1 -241291 0; #X obj 71 224 + 1; #X obj 37 223 f; #X msg 163 56 0; #X obj 163 1 loadbang; #N canvas 337 282 345 318 sec-to-time-symbol 0; #X obj 13 7 inlet; #X obj 14 291 outlet; #X obj 13 63 % 60; #X obj 231 95 int; #X obj 182 6 import zexy; #X obj 95 124 change -1; #X obj 95 72 / 60; #X obj 231 69 / 3600; #X obj 95 98 int; #X obj 13 34 t f f f; #X obj 231 121 change -1; #X obj 231 177 makesymbol %s; #X obj 95 208 list prepend; #X obj 14 237 list prepend; #X obj 95 150 % 60; #X obj 14 264 makesymbol %s:%02s:%02s; #X obj 95 177 makesymbol %02s; #X obj 13 89 list; #X obj 231 149 % 100; #X connect 0 0 9 0; #X connect 2 0 17 0; #X connect 3 0 10 0; #X connect 5 0 14 0; #X connect 6 0 8 0; #X connect 7 0 3 0; #X connect 8 0 5 0; #X connect 9 0 2 0; #X connect 9 1 6 0; #X connect 9 2 7 0; #X connect 10 0 18 0; #X connect 11 0 12 1; #X connect 12 0 13 1; #X connect 13 0 15 0; #X connect 14 0 16 0; #X connect 15 0 1 0; #X connect 16 0 12 0; #X connect 17 0 13 0; #X connect 18 0 11 0; #X restore 37 252 pd sec-to-time-symbol; #X obj 3 46 r $0-start; #X obj 124 1 bng 14 250 50 0 $0-start empty empty 17 7 0 10 -4034 -1 -1; #X obj 124 17 bng 14 250 50 0 $0-stop empty empty 17 7 0 10 -258113 -1 -1; #X obj 141 9 bng 14 250 50 0 $0-reset empty empty 17 7 0 10 -262144 -1 -1; #X obj 176 29 r $0-reset; #X obj 80 46 r $0-stop; #X msg 3 71 1; #X msg 80 71 0; #X obj 37 121 f 0; #X msg 199 130 -1; #X obj 113 223 symbol -:--:--; #X obj 37 150 metro 1000; #X obj 37 289 list prepend; #X obj 215 252 f $0; #X obj 163 81 t b b b f f b; #X msg 37 317 ; $1-time_display label $2; #X connect 1 0 2 1; #X connect 2 0 1 0; #X connect 2 0 5 0; #X connect 3 0 20 0; #X connect 4 0 3 0; #X connect 5 0 18 0; #X connect 6 0 12 0; #X connect 10 0 3 0; #X connect 11 0 13 0; #X connect 12 0 14 0; #X connect 13 0 14 0; #X connect 14 0 17 0; #X connect 15 0 1 0; #X connect 16 0 18 0; #X connect 17 0 2 0; #X connect 18 0 21 0; #X connect 19 0 18 1; #X connect 20 0 14 0; #X connect 20 1 16 0; #X connect 20 2 15 0; #X connect 20 3 2 0; #X connect 20 4 17 0; #X connect 20 5 19 0; #X coords 0 -1 1 30 158 32 1 0 0;
On Mon, 23 Feb 2009, Phil Stone wrote:
Just to see the magnitude of the issue, I made a little test patch (attached) called [symbol_pig]. It just creates symbols, very fast. A very rough measurement based on watching resident memory increasing in bash's top command indicates that (on OS X 10.4), a megabyte is used up for approximately every 32,000 symbols.
Each t_symbol is a 12-byte malloc (double that in 64-bit mode) and another malloc the size of the text plus one. Malloc overhead varies (as I said in the previous mail), but if you add 4 bytes and round to the next multiple of 16, that's almost the least RAM a malloc-function can use up for your malloc. So, 16+16=32 bytes per small symbol, that makes a megabyte.
_ _ __ ___ _____ ________ _____________ _____________________ ... | Mathieu Bouchard - tél:+1.514.383.3801, Montréal, Québec
Hallo, Phil Stone hat gesagt: // Phil Stone wrote:
Frank Barknecht wrote:
A fix for this maketime would be to reuse the symbols ":00" ... ":59" for minutes and hours by using two [cnv] objects for these. Then you would be able to let the clock run for decades before you get into trouble with the symbol table.
I've pondered this, and can't figure out what you mean, unless you're
suggesting having 60 canvases, one for each possible number?
No, only two canvases, one for minutes, one for seconds. See attachment. This way you only ever generate 60 different symbols. As existing symbols are reused, your memory usage doesn't grow after that.
Just to see the magnitude of the issue, I made a little test patch
(attached) called [symbol_pig]. It just creates symbols, very fast. A
very rough measurement based on watching resident memory increasing in
bash's top command indicates that (on OS X 10.4), a megabyte is used up
for approximately every 32,000 symbols.
So you can generate 128 million different symbols with a 4 GB RAM machine. :)
Personally I'd do heavy text processing in something like pdlua. Pd feels awkward when processing text.
Frank Barknecht Do You RjDj.me? _ ______footils.org__
Frank Barknecht wrote:
Hallo, Phil Stone hat gesagt: // Phil Stone wrote:
Frank Barknecht wrote:
A fix for this maketime would be to reuse the symbols ":00" ... ":59" for minutes and hours by using two [cnv] objects for these. Then you would be able to let the clock run for decades before you get into trouble with the symbol table.
I've pondered this, and can't figure out what you mean, unless you're
suggesting having 60 canvases, one for each possible number?No, only two canvases, one for minutes, one for seconds. See attachment. This way you only ever generate 60 different symbols. As existing symbols are reused, your memory usage doesn't grow after that.
Oh! Very good. I didn't realize that an identical symbol would get re-used. For completeness' sake, I will make a new [ps-stopwatch] that does not leak (and is plain vanilla, to boot).
Cheers, Frank.
Phil
On Mon, 2009-02-23 at 13:55 -0800, Phil Stone wrote:
Frank Barknecht wrote:
Hallo, Phil Stone hat gesagt: // Phil Stone wrote:
Frank Barknecht wrote:
A fix for this maketime would be to reuse the symbols ":00" ... ":59" for minutes and hours by using two [cnv] objects for these. Then you would be able to let the clock run for decades before you get into trouble with the symbol table.
I've pondered this, and can't figure out what you mean, unless you're
suggesting having 60 canvases, one for each possible number?No, only two canvases, one for minutes, one for seconds. See attachment. This way you only ever generate 60 different symbols. As existing symbols are reused, your memory usage doesn't grow after that.
Oh! Very good. I didn't realize that an identical symbol would get re-used. For completeness' sake, I will make a new [ps-stopwatch] that does not leak (and is plain vanilla, to boot).
concerning symbol table pollution, it is probably the best strategy to use messages of the form 'list do this and probably that' instead of 'symbol do-this-and-probably-that', and to use a single global [send GLOBAL] and route all messages accordingly :
[r GLOBAL] | [route do] | [route this] | [route and]
etc.
this way you can pass a very big number of messages around to a big number of receivers without really polluting the symbol table.
roman
Telefonate ohne weitere Kosten vom PC zum PC: http://messenger.yahoo.de
On Mon, 23 Feb 2009, Phil Stone wrote:
Oh! Very good. I didn't realize that an identical symbol would get re-used. For completeness' sake, I will make a new [ps-stopwatch] that does not leak (and is plain vanilla, to boot).
Yes, it's re-used, which sort of goes with the fact that it doesn't get de-allocated, but that is also because it's less trouble (for pd itself) to have eternal symbols than mortal symbols.
But the re-use also goes with the fact that it's easier and faster to compare two symbol addresses (t_symbol *) than two string contents, and if pd _ensures_ re-use, then two identical addresses _mean_ two identical strings.
But all this pd symbol concept comes essentially as-is from 1961 LISP. It was then adopted by LOGO and Smalltalk in addition to all of the LISP variants, and then by Ruby, and then the Ruby guys figured out that in the end, a symbol type could be pretty useless if you had a good enough string type, so they almost merged them. Most other languages just have had a string type and improved on that instead of having symbol-vs-string or just symbols. All this to say I'm in favour of replacing symbols with strings (while still calling them "symbols" just because).
_ _ __ ___ _____ ________ _____________ _____________________ ... | Mathieu Bouchard - tél:+1.514.383.3801, Montréal, Québec
Hallo, Mathieu Bouchard hat gesagt: // Mathieu Bouchard wrote:
On Mon, 23 Feb 2009, Phil Stone wrote:
Oh! Very good. I didn't realize that an identical symbol would get
re-used. For completeness' sake, I will make a new [ps-stopwatch] that does not leak (and is plain vanilla, to boot).Yes, it's re-used, which sort of goes with the fact that it doesn't get de-allocated, but that is also because it's less trouble (for pd itself) to have eternal symbols than mortal symbols.
But the re-use also goes with the fact that it's easier and faster to
compare two symbol addresses (t_symbol *) than two string contents, and
if pd _ensures_ re-use, then two identical addresses _mean_ two identical strings.But all this pd symbol concept comes essentially as-is from 1961 LISP. It was then adopted by LOGO and Smalltalk in addition to all of the LISP
variants, and then by Ruby, and then the Ruby guys figured out that in the end, a symbol type could be pretty useless if you had a good enough string type, so they almost merged them. Most other languages just have had a string type and improved on that instead of having symbol-vs-string or just symbols. All this to say I'm in favour of replacing symbols with
strings (while still calling them "symbols" just because).
Is there a difference between symbols and immutable strings like Lua or Java have them?
Frank Barknecht Do You RjDj.me? _ ______footils.org__
On Tue, 24 Feb 2009, Frank Barknecht wrote:
Is there a difference between symbols and immutable strings like Lua or Java have them?
Immutable strings are deallocatable.
If this happened to pd symbols that they became deallocatable, then externs couldn't keep a t_symbol pointer unless they register that they want it to stay alive. But if pd is to have a transition like that, it needs to have versioning of the pd interface used by externals, so that an external says that it wants it new-style, and that any old-style external receiving a t_symbol* will cause the t_symbol to become eternal.
New-style externs would also need to init and deinit t_atom[] structures, whereas old-style externs don't do it. SET-macros would be required instead of messing with atom fields directly. Most of the extra code could be avoided if using C++ instead of C.
_ _ __ ___ _____ ________ _____________ _____________________ ... | Mathieu Bouchard - tél:+1.514.383.3801, Montréal, Québec
On Mon, 2009-02-23 at 22:42 +0100, Frank Barknecht wrote:
Personally I'd do heavy text processing in something like pdlua. Pd feels awkward when processing text.
but even if you do not heavy text processing, there are ways to pollute the symbol table heavily. it is sufficient to only display the results of the text processing in pd (in a canvas or GEM [text3d]) to pollute it. for instance, when using OSC, probably every message is a new symbol. so i guess, it cannot be avoided, even if text processing is done outside of pd, unless a string type is introduced (is that correct?).
roman
Telefonate ohne weitere Kosten vom PC zum PC: http://messenger.yahoo.de
On Mon, 23 Feb 2009, Roman Haefeli wrote:
for instance, when using OSC, probably every message is a new symbol. so i guess, it cannot be avoided, even if text processing is done outside of pd, unless a string type is introduced (is that correct?).
Every OSC target is a symbol, just like every receive-symbol is a symbol; but furthermore, even hierarchical names like /foo/bar are recorded as a single name that doesn't use "foo" and "bar", instead of using a list. Similarly, abstraction instances are _the_ way to flood the table, as all the local receive-symbols and other local symbols get multiplied by the number of instances.
I proposed several solutions to this. Having deallocatable symbols only is useful if you deallocate abstractions and reallocate them... usually has to do with dynamic patching. The other solution would be to make the symbol-table only a table of symbols, and have a separate receiver-table, which would get accessed by ($0,symbol) pairs so that the $0 doesn't get pasted inside of the symbol so that no more symbols need be generated. That would be quite a major overhaul, but it's pretty much the only real solution.
I don't think that there's anything else in OSC that could be wasting symbols. However, if you have a system where you use 1000000 OSC-paths to represent an array of 1000000 numbers, you may be looking for trouble.
_ _ __ ___ _____ ________ _____________ _____________________ ... | Mathieu Bouchard - tél:+1.514.383.3801, Montréal, Québec
Mathieu Bouchard wrote:
On Mon, 23 Feb 2009, Roman Haefeli wrote:
for instance, when using OSC, probably every message is a new symbol. so i guess, it cannot be avoided, even if text processing is done outside of pd, unless a string type is introduced (is that correct?).
Every OSC target is a symbol, just like every receive-symbol is a symbol; but furthermore, even hierarchical names like /foo/bar are recorded as a single name that doesn't use "foo" and "bar", instead of using a list. Similarly, abstraction instances are _the_ way to flood the table, as all the local receive-symbols and other local symbols get multiplied by the number of instances.
I proposed several solutions to this. Having deallocatable symbols only is useful if you deallocate abstractions and reallocate them... usually has to do with dynamic patching. The other solution would be to make the symbol-table only a table of symbols, and have a separate receiver-table, which would get accessed by ($0,symbol) pairs so that the $0 doesn't get pasted inside of the symbol so that no more symbols need be generated. That would be quite a major overhaul, but it's pretty much the only real solution.
I don't think that there's anything else in OSC that could be wasting symbols. However, if you have a system where you use 1000000 OSC-paths to represent an array of 1000000 numbers, you may be looking for trouble.
Since OSC messages have some value concatenated to the end, aren't they
all potentially unique and therefore consumers of new symbols? E.g.,
"/oscillator/frequency 440.0" and "/oscillator/frequency 449.365"
require distinct symbols, don't they? And to think I was worried about
a little stopwatch! :-)
Phil
Phil Stone wrote:
Mathieu Bouchard wrote:
On Mon, 23 Feb 2009, Roman Haefeli wrote:
for instance, when using OSC, probably every message is a new symbol. so i guess, it cannot be avoided, even if text processing is done outside of pd, unless a string type is introduced (is that correct?).
Every OSC target is a symbol, just like every receive-symbol is a symbol; but furthermore, even hierarchical names like /foo/bar are recorded as a single name that doesn't use "foo" and "bar", instead of using a list. Similarly, abstraction instances are _the_ way to flood the table, as all the local receive-symbols and other local symbols get multiplied by the number of instances.
I proposed several solutions to this. Having deallocatable symbols only is useful if you deallocate abstractions and reallocate them... usually has to do with dynamic patching. The other solution would be to make the symbol-table only a table of symbols, and have a separate receiver-table, which would get accessed by ($0,symbol) pairs so that the $0 doesn't get pasted inside of the symbol so that no more symbols need be generated. That would be quite a major overhaul, but it's pretty much the only real solution.
I don't think that there's anything else in OSC that could be wasting symbols. However, if you have a system where you use 1000000 OSC-paths to represent an array of 1000000 numbers, you may be looking for trouble.
Since OSC messages have some value concatenated to the end, aren't they all potentially unique and therefore consumers of new symbols? E.g.,
"/oscillator/frequency 440.0" and "/oscillator/frequency 449.365" require distinct symbols, don't they? And to think I was worried about a little stopwatch! :-)
On further reflection, the OSC path (which *is* a symbol) and the value (which *may* be a symbol, but is more typically a float) are two list items, so the answer to my question is no, I think.
Phil
On Mon, 23 Feb 2009, Frank Barknecht wrote:
Phil Stone hat gesagt: // Phil Stone wrote:
bash's top command indicates that (on OS X 10.4), a megabyte is used up for approximately every 32,000 symbols.
So you can generate 128 million different symbols with a 4 GB RAM machine. :)
Not quite. Past 2 GB RAM you will get into segmentation problems... I don't know where exactly, as I'm still running with 0.25 GB. I think I was told it was somewhere between 3 GB and 3.5 GB... at least part of the address-space is reserved as kernel-space, part of it is reserved for the main executable and the dynamic libraries... fortunately, you don't have memory really specific to the stack, as stack+heap are one pool where heap grows from the start and stack grows from the end.
So you probably can't go much farther than 96 million different symbols unless you run it in 64-bit mode. :)
_ _ __ ___ _____ ________ _____________ _____________________ ... | Mathieu Bouchard - tél:+1.514.383.3801, Montréal, Québec