|
From: Ethan M. <merritt@u.washington.edu> - 2004-09-27 18:07:54
|
This may be a stupid question, but is there not a much more straightforward way of handling this? The basic layout of gnuplot_x11 is that commands are read from the input stream and either (a) executed immediately (e.g. "close window #5") or (b) stored in a list to be executed every time the current plot is redrawn. Right now setting the palette is treated as category (a). That is, the routine scan_palette_from_buf() is executed immediately but the information is not stored with the plot. Can't you fix this problem by moving the operation into category (b) instead? Just store the stream of palette information as part of the plot, and then execute scan_palette_from_buf() each time the plot is redrawn. I don't know what the speed impact of this might be. But if it works at all, you could worry later about optimizing it by keeping some sort of global flag that tracks the last palette loaded, and skip the reload if it hasn't changed. -- Ethan A Merritt merritt@u.washington.edu Biomolecular Structure Center Mailstop 357742 University of Washington, Seattle, WA 98195 |
|
From: Daniel J S. <dan...@ie...> - 2004-09-27 20:52:20
|
Petr,
Daniel J Sebald wrote:
> My thought was as follows: PaletteMake creates a cmap structure:
>
>
>
> typedef struct cmap_t {
> Colormap colormap;
> unsigned long colors[Ncolors]; /* line colors */
> #ifdef PM3D
> unsigned long xorpixel; /* line colors */
> int total;
> int allocated;
> unsigned long *pixels; /* pm3d colors */
> #endif
> } cmap_t;
I'm thinking that in the case that a palette comes across the pipe and
it is different from that of the current_plot, the palette code should
also search the linked list for a colormap that matches the one sent
across the pipe. It doesn't seem too far-fetched to me that someone
experimenting with color maps would go back and forth between maps a lot
of times. The result could be, similar to the previous discussion, the
same color map stored in memory many, many times.
So does it seem worthwhile including inside the above structure an
instance of t_sm_palette, so that we may have quick comparisons in the
case of palettes that are a color formula as opposed to user-defined
gradients? (Of course, I wouldn't store the gradient colors *and* the
color map pixels because that would be real bloat.) Or should we just
stick to what I described previously, and if someone has a lot of varied
palettes of very large size visible and is switching back and forth
between them they will just have to live with it.
In some sense, for harmony or parsimony, or whatever you want to call
it, between gnuplot_x11 and gnuplot, the frequency of sending the
palette over the link should match how often gnuplot_x11 really needs
it. As Ethan pointed out, there are couple schemes:
The basic layout of gnuplot_x11 is that commands are read from the input
stream and either
(a) executed immediately (e.g. "close window #5")
or (b) stored in a list to be executed every time the current plot is redrawn.
In the former case, gnuplot should only be sending over the palette when
it changes. In the latter, gnuplot should send every time so that it
goes into the plot buffer. Right now, gnuplot_x11 is set up for (a),
but gnuplot sends the palette every time a plot is done. That would
prevent gnuplot_x11 from testing every plot if the palette changed.
Just nit-picking I guess.
Dan
|
|
From: Daniel J S. <dan...@ie...> - 2004-09-27 21:07:34
|
Daniel J Sebald wrote: > So does it seem worthwhile including inside the above structure an > instance of t_sm_palette, so that we may have quick comparisons in the > case of palettes that are a color formula as opposed to user-defined > gradients? (Of course, I wouldn't store the gradient colors *and* the > color map pixels because that would be real bloat.) Or should we just > stick to what I described previously, and if someone has a lot of > varied palettes of very large size visible and is switching back and > forth between them they will just have to live with it. Ah... no need for the extra t_sm_palette. If searching through a, for some reason, long list of color maps, when they differ that should fail pretty quickly. So then the only people with slowed down response would be those with... lot's of plot windows open with lots of different color maps of large size and the colormaps only differ by the very last entry in the pixel[] array. All other normal users should be fine. Dan |
|
From: Ethan M. <merritt@u.washington.edu> - 2004-09-27 21:08:19
|
On Monday 27 September 2004 02:18 pm, Daniel J Sebald wrote: > it. As Ethan pointed out, there are couple schemes: > > The basic layout of gnuplot_x11 is that commands are read from the input > stream and either > (a) executed immediately (e.g. "close window #5") > or (b) stored in a list to be executed every time the current plot is redrawn. > > > In the former case, gnuplot should only be sending over the palette when > it changes. In the latter, gnuplot should send every time so that it > goes into the plot buffer. Right now, gnuplot_x11 is set up for (a), > but gnuplot sends the palette every time a plot is done. That would > prevent gnuplot_x11 from testing every plot if the palette changed. It is strictly necessary for x11.trm to send the palette with each new plot, because it has no way of knowing which if any of the previous plots are still active in gnuplot_x11. Why don't you switch gnuplot_x11 over to using scheme (b), and we can see just how much of a hit we take in execution time. -- Ethan A Merritt merritt@u.washington.edu Biomolecular Structure Center Mailstop 357742 University of Washington, Seattle, WA 98195 |
|
From: Daniel J S. <dan...@ie...> - 2004-09-27 21:22:24
|
Ethan Merritt wrote: >On Monday 27 September 2004 02:18 pm, Daniel J Sebald wrote: > > >>it. As Ethan pointed out, there are couple schemes: >> >>The basic layout of gnuplot_x11 is that commands are read from the input >>stream and either >> (a) executed immediately (e.g. "close window #5") >>or (b) stored in a list to be executed every time the current plot is redrawn. >> >> >>In the former case, gnuplot should only be sending over the palette when >>it changes. In the latter, gnuplot should send every time so that it >>goes into the plot buffer. Right now, gnuplot_x11 is set up for (a), >>but gnuplot sends the palette every time a plot is done. That would >>prevent gnuplot_x11 from testing every plot if the palette changed. >> >> > >It is strictly necessary for x11.trm to send the palette with each new >plot, because it has no way of knowing which if any of the previous >plots are still active in gnuplot_x11. > >Why don't you switch gnuplot_x11 over to using scheme (b), >and we can see just how much of a hit we take in execution time. > Because I'm almost done with scheme (a)... changing over to scheme (b) is the same amount of headaches. Saving it in the buffer is easy enough, but then have to add the code to handle it when it comes out of the buffer, i.e., recolor the window. Maybe not too bad. Then there are the unforseen things like maybe the palette has to be the first thing in the buffer otherwise the plotted elements will first be in one color map and then half-way though the plot switch over to another color map. Dan |
|
From: Ethan M. <merritt@u.washington.edu> - 2004-09-27 21:42:32
|
On Monday 27 September 2004 02:49 pm, Daniel J Sebald wrote: > > The basic layout of gnuplot_x11 is that commands are read from the input > > stream and either > > (a) executed immediately (e.g. "close window #5") > > or (b) stored in a list to be executed every time the current plot is redrawn. > > > >Why don't you switch gnuplot_x11 over to using scheme (b), > >and we can see just how much of a hit we take in execution time. > > Because I'm almost done with scheme (a)... changing over to scheme (b) > is the same amount of headaches. I'm a bit worried about races if you mix scheme (a) with the replots done under scheme (b). What happens if somebody resizes or otherwise triggers a replot on an old window while you're processing a new palette in the main pipe. Will that corrupt the new palette forever after? What if someone closes an old window (the only remaining user of a palette) just as you start to get a new copy of that same palette. Can you end up with no copies? Two copies? Maybe I worry too much. -- Ethan A Merritt merritt@u.washington.edu Biomolecular Structure Center Mailstop 357742 University of Washington, Seattle, WA 98195 |
|
From: Daniel J S. <dan...@ie...> - 2004-09-27 22:00:53
|
Ethan Merritt wrote: >On Monday 27 September 2004 02:49 pm, Daniel J Sebald wrote: > > > >>>The basic layout of gnuplot_x11 is that commands are read from the input >>>stream and either >>> (a) executed immediately (e.g. "close window #5") >>>or (b) stored in a list to be executed every time the current plot is redrawn. >>> >>>Why don't you switch gnuplot_x11 over to using scheme (b), >>>and we can see just how much of a hit we take in execution time. >>> >>> >>Because I'm almost done with scheme (a)... changing over to scheme (b) >>is the same amount of headaches. >> >> > >I'm a bit worried about races if you mix scheme (a) with the replots >done under scheme (b). > >What happens if somebody resizes or otherwise triggers a replot on >an old window while you're processing a new palette in the main pipe. >Will that corrupt the new palette forever after? > >What if someone closes an old window (the only remaining user of >a palette) just as you start to get a new copy of that same palette. >Can you end up with no copies? Two copies? > >Maybe I worry too much. > All good questions; very good questions. I thought this through a bit last week before trying changes this past weekend. It seems to me that gnuplot_x11 is the one controling program flow here and that is what lessens concern for me. Recall that I set up the closing of plots from the system level as a little queuing system. That is, gnuplot_x11 is the one actually closing plots and X windows, somewhere in its event cycle. The outside error events are just requesting that gnuplot_x11 close windows, etc. in its next event cycle. I thought I saw that the core of gnuplot of x11 looks at events and then handles them, handles drawing commands, etc. So, I think the scenarios you mention above should all complete before a next operation can take place. I'll certainly test out these situations. Dan |
|
From: Daniel J S. <dan...@ie...> - 2004-09-28 09:24:48
Attachments:
palfix_28sep2004.patch.gz
|
OK, I think I have a solid version of the new colormap list scheme. It
needs a good cleaning yet, but give it a try. (The patch is against CVS
from a day or two ago.) There are still some comments printed out when
colormaps are created, deleted, etc. Watch them to see if they make
sense, e.g., a color map is removed when it is not unique, or when it is
no longer needed, etc.
The major change is the PaletteMake() routine. The "recursion" variable
is gone, the colormap is built first and then compared (because
sm_palette is not stored as part of cmap_t), and the comparison is
against the whole of the colormap list. So, where there used to be
palettes_differ() there is now cmaps_differ(), which looks like [if
someone can find a better way of computing the size of the memory block
to compare, let me know]:
/*-----------------------------------------------------------------------------
* cmaps_differ - Compare two colormaps, return 1 if differ.
*---------------------------------------------------------------------------*/
static int
cmaps_differ(cmap_t *cmap1, cmap_t *cmap2)
{
/* First compare non-pointer elements. */
if ( memcmp(&(cmap1->colors[0]), &(cmap2->colors[0]),
(long)&(cmap1->pixels)-(long)&(cmap1->colors[0])) )
return 1;
/* Now compare pointer elements. */
if (cmap1->allocated) {
if (cmap1->pixels && cmap2->pixels) {
if ( memcmp(cmap1->pixels, cmap2->pixels,
cmap1->allocated*sizeof(cmap1->pixels[0])) )
return 1;
} else
return 1;
}
return 0; /* They are the same. */
}
I like the use of memcmp [potentially a fast assembly routine if done
right] versus the individual comparisons inside palettes_differ().
Dan
|
|
From: Daniel J S. <dan...@ie...> - 2004-09-28 09:59:06
|
Daniel J Sebald wrote:
> OK, I think I have a solid version of the new colormap list scheme.
> It needs a good cleaning yet, but give it a try.
I've tried some images in Octave, increasing the palette 2^6, 2^7, etc.
Around 2^14 gnuplot_x11 *really* slows down. I'm talking on the scale
of minutes.
Could it be that:
if (XAllocColor(dpy, new_cmap->colormap, &xcolor)) {
is a slow routine and allocating these colors one at a time is very
slow? Is there some way to assign colors all at once?
Dan
|
|
From: Daniel J S. <dan...@ie...> - 2004-09-28 10:40:19
|
Daniel J Sebald wrote:
> I've tried some images in Octave, increasing the palette 2^6, 2^7,
> etc. Around 2^14 gnuplot_x11 *really* slows down. I'm talking on the
> scale of minutes.
>
> Could it be that:
>
> if (XAllocColor(dpy, new_cmap->colormap, &xcolor)) {
>
> is a slow routine and allocating these colors one at a time is very
> slow? Is there some way to assign colors all at once?
Actually, that may not be the problem. I notice that choosing the max
colors in gnuplot to be 32768 doesn't take too long. So the difference
may be that in Octave the palette is custom and the issue is all the
ASCII encoded palette information going across the gnuplot/gnuplot_x11
pipe and then read using scanf. (I'm not sure.) This could be a little
annoying when working in Octave, although I don't think images often
have a resolution much beyond 12 bits.
However, I would say that if it does turn out to be a problem, once the
colormap is put in X, the window refreshes just fine... so I'm wondering
if *not* always sending the palette information to gnuplot_x11 would be
a good thing to do. I don't see a problem with sending the palette only
when it should be changed. I'll put a toe in that camp for now.
Dan
|
|
From: Petr M. <mi...@ph...> - 2004-09-29 11:20:42
|
> Somehow I managed to get time to show up... I can hazard a guess at where > all the extra CPU time is going, most likely converting ascii characters > to a double value, based upon the fact that rgb1_from_gray() constitutes > 100% in the second example and 0% in the first example. (If I trust the > numbers I'm seeing, that is... why would cumulative seconds be so small if > the command takes 80 seconds to run? Could it be that X is the one really > using the CPU time? Can't be, otherwise there wouldn't be such a drastic > time difference between these two scenarios.) We are back to the complain that the ascii-piped X11 is horribly slow. Binary transfer (aka OS/2's pm.trm) would boost the performance. > Petr, are large numbers of (custom) palette colors a concern? That is, > anything beyound 2^12 levels? I never used palette larger than 256. Usually 100. Note that Octave's default value is 64 -- try: size(gray) I don't know whether Octave users treat "truecolor" photographs, where you need more colors. -- PM |
|
From: Daniel J S. <dan...@ie...> - 2004-09-29 17:25:46
|
Petr Mikulik wrote: >We are back to the complain that the ascii-piped X11 is horribly slow. >Binary transfer (aka OS/2's pm.trm) would boost the performance. > Yes. >I never used palette larger than 256. Usually 100. Note that Octave's >default value is 64 -- try: size(gray) > Well, that's certainly not a problem. >I don't know whether Octave users treat "truecolor" photographs, where you >need more colors. > I'm guessing usually 8 bits. But probably there will be users who have images stored in higher resolution than needed, yet will want the large palette even though it's superfluous. Wait to see if someone complains. Dan |
|
From: Daniel J S. <dan...@ie...> - 2004-09-27 21:46:40
|
> > Ethan Merritt wrote: > >> It is strictly necessary for x11.trm to send the palette with each new >> plot, because it has no way of knowing which if any of the previous >> plots are still active in gnuplot_x11. > True, sort of. In the scheme I have in mind, gnuplot_x11 always retains the current_ map, even if there are no plot windows open. Said another way, when a window closes the color map pointer for that window is checked against the color map pointer of all other windows *and* current_map. If it is not used somewhere else, then the color map is freed. Dan |
|
From: Daniel J S. <dan...@ie...> - 2004-09-27 21:50:54
|
Daniel J Sebald wrote: >> >> Ethan Merritt wrote: >> >>> It is strictly necessary for x11.trm to send the palette with each new >>> plot, because it has no way of knowing which if any of the previous >>> plots are still active in gnuplot_x11. >> >> > > True, sort of. In the scheme I have in mind, gnuplot_x11 always > retains the current_ map, even if there are no plot windows open. > Said another way, when a window closes the color map pointer for that > window is checked against the color map pointer of all other windows > *and* current_map. If it is not used somewhere else, then the color > map is freed. The one problem would be if gnuplot_x11 crashes and gnuplot starts up another version of it. If gnuplot doesn't send a palette, out of luck. However, I've not seen gnuplot_x11 crash unexpectedly in a long time. I guess I'm fine with palette being sent all the time. Just a bit of extra testing. Dan |
|
From: Ethan M. <merritt@u.washington.edu> - 2004-09-27 22:30:32
|
On Monday 27 September 2004 03:27 pm, Daniel J Sebald wrote: > > Ethan Merritt wrote: > > >I'm a bit worried about races if you mix scheme (a) with the replots > >done under scheme (b). > > > I thought I saw that the core of gnuplot of x11 looks at events and then > handles them, handles drawing commands, etc. So, I think the scenarios > you mention above should all complete before a next operation can take > place. I don't think so. The main loop does a select() at line 817 of gplt_x11.c that mixes input from the pipe (line 849) and from X events (line 844). I see nothing to stop an X event from slipping in between two successive reads from the input pipe. > That is, gnuplot_x11 is the one actually closing > plots and X windows, somewhere in its event cycle. The outside error > events are just requesting that gnuplot_x11 close windows, etc. Not be relevant to the current point, but that's not true either. Yes, if you type "q" or "ctrl-q" then it's gnuplot_x11 that actually closes the plot window. But if you select XKill or some window manager function to close the plot window then I think it's already gone by the time gnuplot_x11 finds out about it. -- Ethan A Merritt merritt@u.washington.edu Biomolecular Structure Center Mailstop 357742 University of Washington, Seattle, WA 98195 |
|
From: Daniel J S. <dan...@ie...> - 2004-09-28 09:11:03
|
Ethan Merritt wrote:
>On Monday 27 September 2004 03:27 pm, Daniel J Sebald wrote:
>
>
>>Ethan Merritt wrote:
>>
>>
>>
>>>I'm a bit worried about races if you mix scheme (a) with the replots
>>>done under scheme (b).
>>>
>>>
>>>
>>I thought I saw that the core of gnuplot of x11 looks at events and then
>>handles them, handles drawing commands, etc. So, I think the scenarios
>>you mention above should all complete before a next operation can take
>>place.
>>
>>
>
>I don't think so. The main loop does a select() at line 817 of gplt_x11.c
>that mixes input from the pipe (line 849) and from X events (line 844).
>I see nothing to stop an X event from slipping in between two successive
>reads from the input pipe.
>
Line 817... OK, I see that. Let me think it over. My point is that all
the graphics stuff in response to X events is done by gnuplot_x11 inside
this loop:
do {
XNextEvent(dpy, &xe);
process_event(&xe);
} while (XPending(dpy));
Am I understanding correctly that with this configuration the X events
can come at any time, but they are processed in an orderly fashion? I
don't think there are any events initiated by X that can suddenly change
current_plot or current_cmap, which are what the information coming
across the pipe pertains to.
But you are right that something must go awry if, say, a window is
closed when only half the plot information has been put through a pipe.
You probably don't remember, but we did once wonder what should happen
when the current_plot is closed. Should we make another plot current?
Or just set current_plot to NULL. We went with setting it to NULL,
which is probably the more wise thing to do. The reason is you can
react accordingly, e.g., open a new plot window (with the
"most_recent_plot_number", something we talked about a couple weeks
ago), or do nothing if current_plot is NULL until a new 'G' or 'N'
command comes along to redo a plot.
I think I'm getting off course here, but my point is that there does
seem to be graceful behavior for this.
>>That is, gnuplot_x11 is the one actually closing
>>plots and X windows, somewhere in its event cycle. The outside error
>>events are just requesting that gnuplot_x11 close windows, etc.
>>
>>
>
>Not be relevant to the current point, but that's not true either.
>Yes, if you type "q" or "ctrl-q" then it's gnuplot_x11 that actually closes
>the plot window. But if you select XKill or some window manager function
>to close the plot window then I think it's already gone by the time gnuplot_x11
>finds out about it.
>
OK, XKill. I've not investigated, but is the XKill the little box in
the upper right corner of an X window, with the 'x'? From what I
remember, pressing that button is what causes X to call the routine:
ErrorHandler(Display * display, XErrorEvent * error_event)
which queues up a plot to be removed, not too far after gnuplot_x11's X
processing loop above. (I'm watching the DEBUG commands in stderr to
verify this.) I'm sure there are other ways for X to close a window,
but until some X-Man (i.e., true superhero) pinpoints other ways, I'm
not compelled to hunt for them.
I see my window manager has a "kill app" associated with each window.
However, that doesn't kill a window, it kills the app that owns the
window and leaves gnuplot_x11 defunct.
We'll just see how it behaves and if we can break it.
Dan
|
|
From: Ethan M. <merritt@u.washington.edu> - 2004-09-28 16:56:06
|
On Tuesday 28 September 2004 02:38 am, Daniel J Sebald wrote:
> Line 817... OK, I see that. Let me think it over. My point is that all
> the graphics stuff in response to X events is done by gnuplot_x11 inside
> this loop:
>
> do {
> XNextEvent(dpy, &xe);
> process_event(&xe);
> } while (XPending(dpy));
>
> Am I understanding correctly that with this configuration the X events
> can come at any time, but they are processed in an orderly fashion?
They are processed in order, yes. But each pass through the main loop
will either deal with input from the pipe or with a queue of X events,
whichever is seen first. The two types of input are asynchronous.
> I don't think there are any events initiated by X that can suddenly change
> current_plot or current_cmap, which are what the information coming
> across the pipe pertains to.
current_cmap must be something you added, so I don't know
how it is handled.
But unless I am remembering incorrectly, everything else is subject to
arbitrary change because you can bind any operation at all to a hotkey,
and the hotkey is recognized and executed as an X event.
Isn't that right? This is admittedly perverse, but consider the case
bind K "set term x11 7; set palette gray; replot"
Now suppose I hit K in a plot window while your code is reading
from the pipe. Will your code survive have the terminal closed,
re-opened and replotted with a different palette in mid-stream?
> We'll just see how it behaves and if we can break it.
Race conditions can be very hard to find by trail and error.
You really need to think about these issues while designing
the code in the first place.
--
Ethan A Merritt merritt@u.washington.edu
Biomolecular Structure Center
Mailstop 357742
University of Washington, Seattle, WA 98195
|
|
From: Daniel J S. <dan...@ie...> - 2004-09-28 18:46:10
|
Ethan Merritt wrote:
>On Tuesday 28 September 2004 02:38 am, Daniel J Sebald wrote:
>
>
>>Line 817... OK, I see that. Let me think it over. My point is that all
>>the graphics stuff in response to X events is done by gnuplot_x11 inside
>>this loop:
>>
>> do {
>> XNextEvent(dpy, &xe);
>> process_event(&xe);
>> } while (XPending(dpy));
>>
>>Am I understanding correctly that with this configuration the X events
>>can come at any time, but they are processed in an orderly fashion?
>>
>>
>
>They are processed in order, yes. But each pass through the main loop
>will either deal with input from the pipe or with a queue of X events,
>whichever is seen first. The two types of input are asynchronous.
>
That's fine. So long as none of the X event code changes "current_plot"
or similar such variables, or modifies X graphics I think we're in good
shape.
>>I don't think there are any events initiated by X that can suddenly change
>>current_plot or current_cmap, which are what the information coming
>>across the pipe pertains to.
>>
>>
>
>current_cmap must be something you added, so I don't know
>how it is handled.
>
>But unless I am remembering incorrectly, everything else is subject to
>arbitrary change because you can bind any operation at all to a hotkey,
>and the hotkey is recognized and executed as an X event.
>Isn't that right? This is admittedly perverse, but consider the case
> bind K "set term x11 7; set palette gray; replot"
>
That is perverse. But how can this find intermix with what is coming
across the pipe? For example, wouldn't it be something like
plot "superslowplot"
<press K while info transferring across pipe, the above bindings get queued>
<plot finishes and returns to command line>
set term x11 7
set palette gray
replot
The X event processing isn't directly changing current_plot (i.e., set
term x11 7). It is simply telling gnuplot to change it... eventually.
>Now suppose I hit K in a plot window while your code is reading
>from the pipe. Will your code survive have the terminal closed,
>re-opened and replotted with a different palette in mid-stream?
>
It should do reasonably well, meaning that it won't crash. That is, if
there are some commands lost you can't expect the plot to make any
sense. But if a replot is done, that will resend all the plot
information and it should be fine.
>>We'll just see how it behaves and if we can break it.
>>
>>
>
>Race conditions can be very hard to find by trail and error.
>You really need to think about these issues while designing
>the code in the first place.
>
I know.
Dan
PS: Ethan, is there a command line configure switch to make gnuplot_x11
work with a profiler? I see a program called "gprof" that I'd like to
apply and see what is taking so long in the palette. I'm not completely
happy with the speed of the custom palette... and may switch back to
palettes_differ() vs. cmaps_differ() if I can't resolve that. Thanks.
|
|
From: Daniel J S. <dan...@ie...> - 2004-09-29 19:40:02
|
Hans-Bernhard Broeker wrote: > Guys, please keep in mind that hidden3d has a switch that lets you turn > *off* the difference between front and back side line types: > > set hidden offset 0 > > So in searching for the reason of this, someone should make sure it's > not caused by world2.dem leaving this option in effect, and 'reset' > forgetting to reset it. That's it. 'reset' doesn't reset the "set hidden offset 0" set hidden offset 0 reset load 'animate.dem' duplicates the behavior. Dan |
|
From: Ethan M. <merritt@u.washington.edu> - 2004-09-29 20:47:58
|
On Wednesday 29 September 2004 01:07 pm, Daniel J Sebald wrote: > > That's it. 'reset' doesn't reset the "set hidden offset 0" In fact, it doesn't reset anything to do with hidden3d. It's a bit messy because the code that sets the default values (hidden3d.c set_hidden3doptions) is a command line parsing routine. Is it acceptable style to call do_string( "set hidden3d default" ) from inside reset_command()? -- Ethan A Merritt merritt@u.washington.edu Biomolecular Structure Center Mailstop 357742 University of Washington, Seattle, WA 98195 |
|
From: Hans-Bernhard B. <br...@ph...> - 2004-09-30 07:26:38
|
Ethan Merritt wrote: > Is it acceptable style to call > do_string( "set hidden3d default" ) > from inside reset_command()? Uhm... no. If hidden3d needs a reset function, it shall have one. But I see you already did that in CVS, Ethan. ;-) |
|
From: Daniel J S. <dan...@ie...> - 2004-09-27 19:02:05
|
Ethan Merritt wrote: >This may be a stupid question, but is there not a much more straightforward >way of handling this? > >The basic layout of gnuplot_x11 is that commands are read from the input >stream and either > (a) executed immediately (e.g. "close window #5") >or (b) stored in a list to be executed every time the current plot is redrawn. > >Right now setting the palette is treated as category (a). That is, the routine >scan_palette_from_buf() is executed immediately but the information is not >stored with the plot. > >Can't you fix this problem by moving the operation into category (b) instead? >Just store the stream of palette information as part of the plot, and then >execute scan_palette_from_buf() each time the plot is redrawn. > Sure. That is one approach. Conceptually, that's not too much different than saving a cmap structure (as opposed to a pointer) for each plot. The issue with this approach is that if, say, there are 10 different plots, all with a similar color map and that colormap is fairly big, then there are ten instances of the color map. I know there is this general feeling now days that "memory is cheap", but when talking a computer system (as opposed to some specific embedded application) I still like to make memory preservation a priority. Hence a linked-list of color maps. Actually, there really isn't too much extra code for a linked list of color maps. (Although, I think we both agree that X is the one that should be handling this if only its TrueColor/DirectColor stuff were easier to work with.) >I don't know what the speed impact of this might be. >But if it works at all, you could worry later about optimizing it by keeping >some sort of global flag that tracks the last palette loaded, and skip the >reload if it hasn't changed. > This probably wouldn't work so good with the scheme of saving the color map in the plot buffer. You'd be better off just recoloring the window and not worrying about whether changes occurred. If one does try this, then it is back to the same question of how do you know it has changed? If one is switching between plots and has to RecolorWindow(), there will be no pointers between which to do comparison because the palette information will be somewhere within the plot buffer. I'm not sure, but I think you'd have to search within the other plot's buffer for the palette information. Dan |
|
From: Daniel J S. <dan...@ie...> - 2004-09-27 20:32:14
|
I see something I consider a memory leak in the gnuplot_x11 palette.
I'm on the downhill side of revamping the MakePalette routine and will
fix this, so I don't know if it is worth fixing in CVS or 4.0 errata.
If you are curious what the problem is, read on...
=========
Considering the case of supplying a gradient or user-defined
(user-defined is implemented as a special type of gradient) the routine
static void
scan_palette_from_buf( plot_struct *plot )
{
t_sm_palette tpal;
will scan a user-defined palette from the pipe. In the case of "case
SMPAL_COLOR_MODE_GRADIENT: {" there is a malloc:
tpal.gradient = (gradient_struct*)
malloc( tpal.gradient_num * sizeof(gradient_struct) );
but this memory is never freed anywhere and you see above that "tpal" is
local, hence this information is discarded.
*However*, this memory can't be freed here. The current CVS version
insided PaletteMake() of gplt_x11.c keeps a record of the most recent
palette sent across the pipe. And inside of there is:
case SMPAL_COLOR_MODE_GRADIENT:
sm_palette.gradient_num = tpal->gradient_num;
sm_palette.gradient = tpal->gradient;
Notice that this doesn't malloc() any memory. It just keeps a record of
the memory that was malloc'd in the scan_palette_from_buf() routine
above. So, if one were to free the memory in scan_palette_from_buf(),
this sm_palette.gradient would be a bogus pointer and later when a
"palettes_differ()" were called, it would crash from accessing invalid
memory.
The bottom line is that nowhere is memory for an outdated gradient
palette discarded. It could be fixed with a few extra mallocs and
frees, but I don't know if it is worth it seeing as I'm almost done with
a re-vamping of the palette stuff.
I've verified this leak by running the imagegp.m script in Octave. The
script uses a gnuplot user-defined palette. If I keep plotting the same
image, the memory consumption for gnuplot_x11 just keeps growing.
Dan
|