Multithreaded C and garbage collection
BlitzMax Forums/BlitzMax Programming/Multithreaded C and garbage collection
| ||
Would there be any advantage to defining objects in C code, creating them in C with a creation function, accessing the members in BlitzMax, and deleting them with a C function? Would this relieve the garbage collector from having to keep track of lots of objects? |
| ||
Would this relieve the garbage collector from having to keep track of lots of objects? If you are still creating BlitzMax objects, no. |
| ||
How are you going to keep track of the C objects? |
| ||
A primitive linked list. For example, each entity would have a member for the next entity, and for its next sibling in the hierarchy. Then C or BMX could read the member/field and get the next one. |
| ||
Edit: Actually, I forgot you can create Extern Types, which basically let you do just that. Now whether there's a significant performance advantage, I know not. tblah.bmx: tblah.c: |
| ||
Ah, you can even do methods. I assume an Externed type is like a regular object, but with no GC performed on it? This code demonstrates that in multithreaded mode, there is definitely a slowdown with more objects: GCSetMode(2) Type thing Field x,y,z,a,b,c,d,e,f,g,h EndType Local list:TList=New TList Print "100 objects, 100 GCCollect calls" For n=0 To 100 list.addlast(New thing) Next time=MilliSecs() For n=0 To 100 GCCollect() Next Print (MilliSecs()-time) list.clear() GCCollect() Print "1000 objects, 100 GCCollect calls" For n=0 To 1000 list.addlast(New thing) Next time=MilliSecs() For n=0 To 100 GCCollect() Next Print (MilliSecs()-time) list.clear() GCCollect() End |
| ||
Ah, you can even do methods. I assume an Externed type is like a regular object, but with no GC performed on it? Yeah, they are basically just like C++ objects. If you use C instead of C++, the code to create methods becomes very messy very quick. |
| ||
C doesn't have methods. My idea is that perhaps I can avoid some of the overhead of the multithreaded garbage collector if I use C++ classes for types that I am not going to be able to rely on the GC for anyways. It is totally redundant to use garbage collection on a type that requires a manual Free() method to be called. |
| ||
C doesn't have methods. Exactly. You probably wouldn't want to decipher the code where I have tried to fake polymorphism with C. My idea is that perhaps I can avoid some of the overhead of the multithreaded garbage collector if I use C++ classes for types that I am not going to be able to rely on the GC for anyways. It is totally redundant to use garbage collection on a type that requires a manual Free() method to be called. Please let us know if you get any results. |
| ||
The time taken by a precise GC (say, as opposed to a reference-counted GC that can't reclaim cycles) is largely determined by the size of the object graph it needs to traverse to look for live objects. So naturally a 1000 item list needs more time than a 100 item list. Even if your list contained pointers to external C objects, the GC would still have to walk all 1000 items. Your Type "thing" doesn't have any reference fields, so the GC doesn't have to follow any links out of a "thing", and so in this case I can't imagine that switching from a native BlitzMax type to an external C type would yield any benefit. Since we don't know the algorithm that the MS GC actually uses, I might be wrong though. ~Jesse |
| ||
The time taken by a precise GC (say, as opposed to a reference-counted GC that can't reclaim cycles) is largely determined by the size of the object graph it needs to traverse to look for live objects. So naturally a 1000 item list needs more time than a 100 item list. Even if your list contained pointers to external C objects, the GC would still have to walk all 1000 items. Walk, yes, but it doesn't have to descend into them for a recursive mark step, right? Your Type "thing" doesn't have any reference fields, so the GC doesn't have to follow any links out of a "thing", and so in this case I can't imagine that switching from a native BlitzMax type to an external C type would yield any benefit. Since we don't know the algorithm that the MS GC actually uses, I might be wrong though. It's a mark-and-sweep algorithm. You can mostly find it in BlitzMax/mod/blitz.mod/blitz_gc_ms.c. From a cursory glance it actually doesn't seem to know about data types, so it would also follow Ints and Floats. |
| ||
Even if your list contained pointers to external C objects, the GC would still have to walk all 1000 items. I don't believe C++ objects can be added to a list anyways, because they can't be cast to a Blitzmax Object type. You would have to store them in some kind of C++ structure or a special BlitzMax container like an array of byte pointers. Of course this allows the possibility of an invalid pointer error, something which is impossible in pure BlitzMax, but our objective here is speed. I think this demonstrates that a kind of GC-less object in BMX might be beneficial: Type TThing {static} Field a:Int EndType t:TThing=New TThing t.Delete() Print(t.a)'error occurs here!!! |
| ||
Here's another less drastic idea: GCSetObjectMode(o:Object,mode:Int) This can be used to remove an object from the object graph, when you know the object isn't going to be collected anyways. You can change the mode back when you are done with the object. Then there is still no risk of an invalid pointer, and you aren't clogging the GC graph up with objects that have to be manually freed anyways. Type Thing Field parent:Thing Field kids:TList=New TList Method New() GCSetObjectMode(Self,False) EndMethod Method Free() If parent parent.kids.remove(Self) parent=Null EndIf For Local t:Thing=EachIn kids t.Free() Next GCSetObjectMode(Self,True) EndMethod EndType Local t:Thing=New Thing t.Free() |