Thread overview
Difference between DList and SList from garbage collector point of view
Feb 24, 2013
Alexandr Druzhinin
Feb 24, 2013
monarch_dodra
Feb 26, 2013
Alexandr Druzhinin
February 24, 2013
I used in my application DList (code is large and I couldn't reduce it) and the application allocates memory always. I can not realize why and don't know it now. But when I replaced DList by SList (and even dynamic array) memory leaks disappeared at all and all works as expected. I know it is hard to help me without code but what may be reason of this? May be I don't know some simple things I should and just misuse DList?

About code causing memory leaks - it is trivial loop:

	class DataChunk {
	...
	}

	DList!DataChunk patch;
	(RedBlackTree!DataChunk)[uint] _container_map;

	...	

	foreach(datachunk; find!isNewer(_container_map[source][])) {
	    patch.insertFront(datachunk);
	}

if I replace DList by SList all works fine - size of used memory is the same all the time. But with DList the application uses memory more and more.
February 24, 2013
On Sunday, 24 February 2013 at 20:16:26 UTC, Alexandr Druzhinin wrote:
> I used in my application DList (code is large and I couldn't reduce it) and the application allocates memory always. I can not realize why and don't know it now. But when I replaced DList by SList (and even dynamic array) memory leaks disappeared at all and all works as expected. I know it is hard to help me without code but what may be reason of this? May be I don't know some simple things I should and just misuse DList?
>
> About code causing memory leaks - it is trivial loop:
>
> 	class DataChunk {
> 	...
> 	}
>
> 	DList!DataChunk patch;
> 	(RedBlackTree!DataChunk)[uint] _container_map;
>
> 	...	
>
> 	foreach(datachunk; find!isNewer(_container_map[source][])) {
> 	    patch.insertFront(datachunk);
> 	}
>
> if I replace DList by SList all works fine - size of used memory is the same all the time. But with DList the application uses memory more and more.

I don't see any any calls to remove, so I'm not sure what the algorithm is. Wouldn't patch just grow and grow and grow?

Regardless, the design of DList is currently flawed (but a pull is open to fix it), in the sense that a DList is just a "handle" on a chain of nodes.

The problem with this approach is that calls to things such as "removeFront()" or "removeFront(n)" merelly reposition the "first" pointer. However, the nodes are never actually un-linked. I'd say there are good chances this is what you are seeing.

Seeing a DList doesn't have splice either, I'm unsure what to tell you in regards to working around it.

I'd say once you are done with a list, you can try to "dup" it: This will allocate *more*, but will allow the GC to collect everything that was previously removed.

...Or just SList. It's "less" bugged.

See this:
http://forum.dlang.org/thread/gjhclwsuqyhrimdeoaec@forum.dlang.org
February 26, 2013
25.02.2013 3:59, monarch_dodra пишет:
>
> I don't see any any calls to remove, so I'm not sure what the algorithm
> is. Wouldn't patch just grow and grow and grow?
>
> Regardless, the design of DList is currently flawed (but a pull is open
> to fix it), in the sense that a DList is just a "handle" on a chain of
> nodes.
>
> The problem with this approach is that calls to things such as
> "removeFront()" or "removeFront(n)" merelly reposition the "first"
> pointer. However, the nodes are never actually un-linked. I'd say there
> are good chances this is what you are seeing.
>
> Seeing a DList doesn't have splice either, I'm unsure what to tell you
> in regards to working around it.
>
> I'd say once you are done with a list, you can try to "dup" it: This
> will allocate *more*, but will allow the GC to collect everything that
> was previously removed.
>
> ...Or just SList. It's "less" bugged.
>
> See this:
> http://forum.dlang.org/thread/gjhclwsuqyhrimdeoaec@forum.dlang.org
After some research I think that this situation is due to several reasons set and DList isn't single cause.
patch is local var:
     class DataChunk {
	uint source_id;
	uint id;
     ...
     }

     class DataStorage {
         DList!DataChunk patch;
         (RedBlackTree!DataChunk)[uint] _container_map;

     ...

	auto getPatch(uint source, long last) {

	    bool isNewer(DataChunk dc) {
		if(dc.source_id == source && dc.id > last)
		    return true;
		else
		    return false;	
	    }

            Patch patch;
            foreach(datachunk; find!isNewer(_container_map[source][])) {
                patch.insertFront(datachunk);
            }
	}
    }	
so it doesn't grow.