3 ms·
Why should I code in C++ idioms if it has significant downsides? An example is I wrote a varadic template for a GC allocation interface: T1* obj1 = Alloc<
by chubot 4y ago
Why should I code in C++ idioms if it has significant downsides?
An example is I wrote a varadic template for a GC allocation interface:
T1* obj1 = Alloc<T1>(arg1)
T2* obj2 = Alloc<T2>(arg2, arg3)
However because I have so many fine-grained types, this seems to takes up 10% of the VM size of the program!
https://www.oilshell.org/release/0.12.5/pub/metrics.wwz/oil-native/overview.txt https://www.oilshell.org/release/0.12.5/pub/metrics.wwz/oil-...
The total vmsize is 1217792 and the 2 Alloc<> entries are about 10% of that.
So my conclusion is that it would have been better to use a macro all along, which would look something like:
T1* obj1 = ALLOC(T1, arg1)
T2* obj2 = ALLOC(T2, arg2, arg3)
This will expand to something like:
T1* obj1 = new (gHeap.Allocate(sizeof(T1)) (arg1)
That is, it uses placement new to constructs the object inside a GC'd heap.
-----
I don't believe the C++ idiom is any faster, and it makes the code larger (and potentially slower).
Am I missing something?
I think the issue is that the monomorphization happens for each T and not for each sizeof(T), and even doing it on sizeof(T) is not really necessary for fast code.
Oil has more fine-grained and ML-style strong types than any other shell implementation, via ASDL and C++. So I try to take advantage of additional type safety. But sometimes it's not worth it. I suspect the macro is better here. It will be somewhat annoying to change all the code, but probably worth it.
- krona 4y agoBreak up Alloc<T> in to templated and (mostly) non-templated parts? Without seeing the code its hard to know.
- chubot 4y agoIt is a tiny function that is basically equivalent to that macro, but using variadic templates: template <typename T, typename... Args> T* Alloc(Args&&... args) { assert(gHeap.is_initialized_); void* place = gHeap.Allocate(sizeof(T)); assert(place != nullptr); // placement new return new (place) T(std::forward<Args>(args)...); } https://github.com/oilshell/oil/blob/master/mycpp/gc_heap.h#L23 https://github.com/oilshell/oil/blob/master/mycpp/gc_heap.h#... So there is nothing to really break up