Go forward in time to January 2006.
Start with a fish. Make sure it is scaled, cleaned, and that it has a few deep cuts along the sides. Today we used a lovely red snapper.
Set up a baking dish with plenty of foil. Wash the fish. Put it in the dish.
Get a bunch of fresh basil. Wash it.
Get rid of the thick stalks, leaving only the leaves.
Spread some olive oil on one side of the fish. Tuck a lot of basil in each of the cuts. Add salt and pepper.
Turn the fish over. Spread olive oil on the other side and tuck basil in its cuts. Put some more basil where the innards used to be. Add more salt and pepper.
Slice some onions and coarsely chop some garlic. Spread them on the fish and under it. Add some slices of butter.
Wrap the foil around the fish. Ensure that the liquids will not spill.
Meanwhile, you'll have preheated the oven to 250 degrees.
We baked this two-kilogram baby for 40 minutes.
Serve hot and enjoy. You can add a few drops of lime and it will be delicious. Preparation time for this was about 20 minutes plus the baking time.
We had an excellent dinner today. Oralia made a cream of cauliflower and sauteed red and green peppers, spiced up with a bit of Brie cheese; she also made smoked pork chops with pineapple slices. I made a Greek green salad. The pork chops were delicious. We got them on Saturday in Perote, a town where they make Spanish-like hams and other cured meats. We also had a nice and smooth 1999 Rioja that we found for cheap in the supermarket.
Robert has some words of wisdom about using threads. One of his points is that whenever people run into a performance problem, or something that blocks the GUI for a while, they automatically think, "put that in a thread!".
If your GUI blocks because you are computing something slowly, adding a thread just gets you complexity. Also, you haven't solved the performance problem; you have just shoved it under the rug. You should start by seeing if you can make the computation faster so that you can keep doing it in the middle of the GUI code. Once you have done that, if it is still not fast enough, you can separate the computation into an object that supports intermediate states. If you are generating an image pixel by pixel, you keep an object that holds the state of the computation (current pixel coordinates, all other state), and then you perform bits of the computation somewhere during the idle loop. This is easy to debug and terminate prematurely: you just free the object and remove the idle handler.
I/O is harder. Ideally you would switch to an API that allows you to do asynchronous I/O. Async APIs make your life a bit harder than writing plainly sequential code, since you need to maintain a state machine of your own (I'm waiting for something to be read - what do I do with it once it's ready?). State machines are easy to debug compared to threads with locking. Also, having just a few async callbacks and a real state machine is generally a better idea than having tons of async callbacks that chain one into the other: the former is easier to debug and extend. If you don't have an async API, your life becomes really hard. It is difficult to know whether you are better served by stuffing the I/O in a thread, or by writing an async API of your own.
Larry, stupid question for you: could you create a GIOChannel for that pipe's file descriptor instead, and g_io_add_watch() on it?
Rich: it looks to me like evolution/a11y/calendar has the same problems are the more exotic parts of GAIL. When you wrap the interfaces in the calendar's GUI code with a11y code without touching the calendar's internals, there's only so much you can do to get deep knowledge of the objects you are wrapping. Rather, you could move some (all?) of the a11y code for complicated widgets like EDayView into those widgets themselves. Getting an a11y-friendly string for your events in the day view would then simply be a matter of putting a few calls to atk_object_set_description() close to where you generate the accessible children for the day view: you can create a string that includes the event's description and its start/end times, and use that for a11y purposes.
You don't need to "reverse-engineer" the widget structure or the accessible object hierarchy: you have the real implementation code which you can tweak. A RE'd solution will break if the calendar views get changes in their structure.
In your specific example, you count the number of rows in the "table" to know the amount of time that each row represents. This will break if Evo starts doing the Palm Pilot thing of compressing the view to only show time spans within the day where events are actually present.
Why we need Dtrace on Linux, part N. You know when you run top(1) and top itself is the program that chews up the most CPU time? Adam Leventhal analyzes why this happens, using Dtrace on Solaris, none the less. Summary: top does many big allocations between 256 KB and 512 KB, and subsequently frees them. This causes a lot of work to happen in munmap(), since glibc uses mmap/munmap for big blocks instead of the "normal" heap for malloc(). It would be better for top(1) to simply reuse that buffer if it can, rather than allocating and freeing it for every use.
This brings me to allocators and the super-awesome new GSlice, courtesy of Tim and Matthias. This is a replacement for the old GMemChunk.
GMemChunks used to let you create allocators for fixed-size blocks. You'll need to allocate many blocks of size K? Create a GMemChunk for that specific size and ask it to allocate blocks for you. GMemChunk works by allocating big chunks of size K*n, and then carving out K-sized blocks out of those chunks.. Unfortunately, even if you tell a particular GMemChunk that you no longer need a block, it won't really give memory back to the system until you free the whole GMemChunk. It also doesn't scale well to multithreaded apps which share the same GMemChunk across threads. Also, the operations required to maintain the free lists in GMemChunk are expensive.
There are two papers that every programmer should read (click on the PDF links on the top-right of these pages):
Look at the dates for each paper. The first paper, written in 1994, describes a very nice allocator similar in spirit to GMemChunk, but without the associated problems. Several years later, that allocator was seen not to scale for multithreading or multi-CPU boxes. So they added another layer on top of it which really makes it scale (it scales linearly with the number of CPUs in terms of the number of allocations/deallocations you can do per second, which is pretty awesome). They considered everything: scalability to many CPUs and threads, behavior of the processor's cache, behavior of the caches of several processors.
So, back to GSlice. It is an implementation in Glib of just that slab allocator plus the magazine layer for multithreading. You don't really need to care about the internal magic to use GSlice. You can just call these functions:
void *my_buffer = g_slice_alloc (my_buffer_size); ... /* use the buffer */ ... g_slice_free1 (my_buffer_size, my_buffer);
Or you can use the preferred form in Glib, which is quasi type-safe:
MyType *my_object = g_slice_new (MyType); ... /* use the object */ ... g_slice_free (MyType, my_object);
If you were using GMemChunk already, you don't really need to do anything: GMemChunk has been converted to just use GSlice internally.
If you need a fast allocator, just use GSlice. As you can see, the only difference between it and malloc/free is that you pass the buffer size to g_slice_free() as well.
This also brings me to Evolution's memory consumption. A long time ago, Evolution took the GMemChunk API and reimplemented it as EMemChunk. EMemChunk is less expensive to operate, but it also doesn't give memory back to the system until you actually free the whole EMemChunk.
Evo uses EMemChunk to store many data structures in Camel, the mail library. The idea was that even if EMemChunk wouldn't give memory back to the system immediately, that memory would get reused during normal operation. We have to figure out if this is actually working as intended.
Tasks for someone interested in reducing Evolution's memory consumption:
Copy all your ~/.evolution to a separate user account.
Log in with that account. Start up Evolution. Visit every mail folder. Find the heap size for the main "evolution" process — this will be mostly the mailer's memory. You can get a rough approximation of the heap size with this:
pmap -x `pidof evolution` | grep rw | awk '{ total += $2 } END { print total }'
Hack EMemChunk (e-memory.c) so that it uses plain malloc()/free() for each requested block, instead of using chunks. Get the heap size: is it bigger/smaller? Run valgrind's "massif" tool to see where the memory gets allocated (this will help us later when we want to see how to reduce the memory consumption in the code by doing something more than replacing the allocator). See if we have memory leaks inside the users of EMemChunk.
Hack EMemChunk so that it uses GSlice internally instead of doing the allocations itself. Get the heap size again: is it bigger/smaller? Does it grow or keep itself more or less constant as you use the same Evolution process for several days?
There is a little benchmark at the bottom of e-memory.c. Run the benchmark before and after each change: the one to use malloc()/free(), and the one to use GSlice.
There is another allocator in e-memory.c, called EMemPool. It uses an EMemChunk or a different pool of memory depending on the requested size for blocks. Replace its implementation with GSlice as well, and take the same measurements as above.
Any volunteers? Knowing the info above would be very valuable to see what our next move should be.
Joakim is writing quite the gems these days.
Øyvind and I spent a lot of our waiting time talking about uses for computers in movie production. There could be a huge amount of stuff done there, for screenwriters, directors, DPs, production people, continuity/script assistants, and whatnot. What’s available today is pretty pathetic in terms of integration and user interface, and I say that as a registered Final Draft user. If free software wanted to completely take over a relatively small, but high profile niche market, that would be it. Open formats, free software, and heavy integration would be perfect for this stuff. (On movie production and obsolete tools)
There were various torture scenes, including one of me lifting Marco by the balls (he was actually suspended under the armpits out of frame). I actually got a decent hold of his balls, and his screaming got more enthusiastic when I squeezed a little. I think that’s what they call Method acting. (On a day at work)
Yesterday Oralia and I went to Veracruz. As usual, we had a lovely time — great seafood, sun, wind, and a leisurely stroll along the center of town. The wind was blowing sand from the beach and a good amount of surf, so that driving with the windows open left you with wet and salty cheeks.
In the evening, we went to browse for CDs. I was delighted to find Money Jungle with Duke Ellington, Charlie Mingus, and Max Roach. That's the album with the great version of Caravan that appears in the inimitable SAMSUNG MEANS TO COME. By the way, the stupid CD was selling for as much as classical imports.
In Gaim, when someone says, "federico: you are on crack", the person who said it gets highlighted in a mustard color that is hard to distinguish among all the text.
if (flags & GAIM_MESSAGE_NICK)
strcpy(color, "#AF7F00");
Indeed.
Oralia's jingling earrings:
While we were in Veracruz, there was a humongously tall maritime drill sitting for repairs at the port.
Microsoft sets up a person to oversee the performance of all their software.
Meanwhile... The non-shared mappings for Evolution:
cacharro$ for i in evolution evolution-data-server-1.4 evolution-alarm-notify evolution-exchange-storage; do (echo -n "$i: "; pmap -x `pidof $i` | grep rw | awk '{ total += $2 } END { print total }'); done
evolution: 152212
evolution-data-server-1.4: 36580
evolution-alarm-notify: 32880
evolution-exchange-storage: 8312
We have a lot of catching up to do.
Apple has a profiler called Shark, with a very pretty GUI (thanks to JRB for the link).
It even suggests what you may want to change in your code (!). Sysprof and Memprof together already have a lot of the machinery to do what Shark does. Who wants to hack Sysprof to be prettier?
Normally, Oralia and I try to procrastinate going to the supermarket until it is an absolute emergency: when we are out of milk [1], when we are out of toilet paper.
Today is such an emergency, for we are out of powdered cinnamon, and you can't make a good capuccino without that.
And speaking of coffee, the gynecologist told us that caffeine is really bad for Oralia. So when we ran out of the lovely Arabica beans that we use for espresso, I went to buy some decaffeinated beans [2]
What are decaf beans like? They are definitely not as aromatic as regular beans. Regular beans have a deliciously sweet smell that caresses your nostrils and your lungs; decaf just "smells like coffee".
What is a decaf capuccino like? It's definitely not as aromatic as a regular one, and by physiological extension not as tasty. My regular capuccinos caress your belly, your soul, and your intestines. A few minutes after drinking one, you get this uncontrollable urge to take a really good dump, the kind that leaves you light as air and relaxed all day [3]. That doesn't happen with the decaf.
Finally, decaf beans are more expensive.
Our gynecologist has definitely not had one of my capuccinos. I'll discuss it with him.
Footnotes:
For unfathomable reasons, one cannot buy fresh milk in Xalapa. One has to buy ultrapasteurized milk, the kind that does not need refrigeration until opened. So we usually buy a 12-pack box, or a bit less, which will last us for about two weeks. When we moved here, it took us about two months to get used to the taste of the ultrapasteurized shit.
Xalapa is a coffee-growing region. When you first ask people about the best coffee beans in town, their default answer will be, "Café Bola de Oro", because that's what the governor of the state used to drink, or something like that. Don't believe them. It's crap. Go to Café Colón instead [4].
Capuccino is a morning ritual, both in our house and in Italy. A good dump is also part of the morning ritual, and in a worrysome way, it doesn't come automatically after a decaf capuccino.
"Café Colón" means "Columbus Coffee", not something related to the digestive tract, even if the side effects described above may lead you to think otherwise.
If you google for "Ximian", you'll get an ad sponsored by Microsoft to use their products instead of ours. Rock on.
Alan Coopersmith has an interesting post about what Sun is doing to improve GDM's loading time. This is exactly the kind of profiling that we need to do throughout GNOME: focus on one particular operation, find out why it is slow, instrument as needed. Link courtesy of Glynn.
If you want to start profiling a big problem ("make Nautilus load directories faster"), take a look at How to do a Good Performance Investigation.
Go backward in time to November 2005.
Federico Mena-Quintero <federico@gnome.org> Tue 2005/Dec/06 10:57:39 CST