Showing posts with label Memory. Show all posts
Showing posts with label Memory. Show all posts

Nov 30, 2007

New Memory Layout

I have «invented» new memory layout for objects. Now creating new objects as well as wrapping simple data in object is very simple. The solution is to keep internal fields at negative offsets. The nm_object function returns pointer inside allocated block, and nm_release is able to find free and destroy methods out of this pointer. Additionally, deallocation of memory and destruction of object is now two different configurable operations. This allows me to create objects on stack or using ob-stacks or any other memory manager.

Working with objects is really simple now. I'm having fun with hacking nm again. :)

Oct 12, 2007

Strings Handling

The idea is to keep length of string together with characters, just like in old WMData structure. In first attempt I allocated buffer with second call to malloc and stored only pointer to character buffer in the object. Then after playing a little with profiler I've changed code to use flexible array for a buffer. That also eliminated the need for WMString-specific destructor. Now I have a function WMCreateString which does basically the same as wstrdup (and a little more, because it at least keeps length of the string), but performs about 10% faster.

The other thing I will certainly need is some function to concatenate mupltiple strings. This function will replace wstrconcat, wstrappend, and also sprintf in many places. What I don't like about existing functions is calls to realloc. It is much better to collect strings to be concatenated in some kind of container like array or list, calculate length of the resulting string, call malloc and copy all data int new string. It would be also good in some situations to have function with variable argument list, that concatenates all its arguments.

I have even more ideas for handling strings. For example it may save a lot of CPU time if there will be string objects that doesn't copy literal strings when it's not absolutely needed, and keeps only pointer to it. Or it could be wise to create objects to represent substrings. They will keep reference to original string, offset, and length. Now I have ideas for at least four differend kind of strings. I think it is a good time to start experimenting with subobjects which will have more methods than just destroy.

Oct 9, 2007

Object System Issues

I have actually started hacking new object system for WINGs. The first thing I have noticed is that I don't want type tags to be dynamically allocated. It's very unclear when to destroy and free memory of such dynamic objects. Pointers to statically allocated objects should work as well.

It was excellent decision to start writing tests. The first thing I stepped on was dynamic type tags, and the second was lack of inheritance in C. WMRetainObject and WMReleaseObject functions now accept pointer to void type as argument as most generic type of pointers. There is no way to specify that function accepts pointers to objects only derived from WMObject structure. Now it is at least possible to use these functions without explicit type casts or some other ways to converting types.

I thought about where to start actually replacing current WINGs' objects with newer ones. It won't be PropLists. PropLists will be replaced almost at the end, just before I'll start hacking widgets. It won't be any of container types. All of them will be replaced little later. First two candidates for replacement is WMData and... strings. I choose to start with strings.

Oct 2, 2007

Reference Counting and Objects

While I was looking at WINGs/memory.c eliminating malloc wrappers, I've found two functions that drew my attention. It was wretain and wrelease. If I'm not mistaken, the original idea was to eliminate all handcrafted reference counting code into one place. This is definitely the Good Thing™. But current implementation just sucks. Using hashtables for storing counters with pointers as a keys is definitely not my way of thinking. And those functions are used only in small number of objects in library, with handcrafted reference counting functions for all other objects.

Let's go into that problem little deeper. WINGs library does have objects. In fact there's at least three kind of objects, with different ways to distinguish types:
  • «raw» data structures like WMArray, WMBag etc with no way to determine type;
  • PropList-wrappers over raw structures with closed set of type tags;
  • widgets with open set of type tags, but with rudimentary support for creating new type tags.
Some of these objects use generalized reference counting and some not. That makes total of six potential object systems with five of them actually implemented. I don't understand why there should be more than one object representing one thing, moreover if those objects have different APIs. I don't understand why there should be more than one object system in single library.

I think I'll replace this object's zoo with something better. I came up with the following idea. Two common fields for all object are almost obvious. These are some kind of a type tag, and a reference counter for that object. The best kind of type tag I can think of is a pointer to a structure with pointers to methods as fields. I'll start it with the single destroy field, which if present will handle additional operations needed to destroy an object. This solution may add just a little overhead to some «raw» objects, and no overhead to all others. They're already have something like counter field, type tags or destructor field. This overhead should pay off when I start replacement of PropLists with new objects.

Sep 28, 2007

MALLOC Wrappers Is Bad

I have found my old messages to wm-core@w.o mailing list. I have to admit that I still agree with most things I've said then. I still think that no library function should print something on the screen unless this is the main goal of the function. As the only exception to this rule I can accept some debugging output I can disable. I remember how much trouble was working with libxml2 which prints various warnings about malformed xml being parsed with no way to disable this. Exactly the same things I think about termination of applications within the library function. I prefer that these decisions should be left for application.

I thought about using Boehm garbage collector library. There's even some experimental code in WindowMaker to use it. It looks like a very appealing idea for a lisper like me. But garbage collectors are generally incompatible with tools like valgrind. And I want to use such tools, at least until I clean up the code. Also, using some garbage collecting library can possibly happen to be incompatible with some future changes like embedding extension language such as guile, which uses own garbage collector.

I decided to eliminate wmalloc, wmalloc0, wrealloc, and wfree functions. Checking return value everywhere malloc is used and reacting gracefully to that condition requires huge amount of work. It will take some time, and probably will be the cause of many other changes. I'll do it in a number of small steps.