-
-
Notifications
You must be signed in to change notification settings - Fork 411
precise GC without array support #1977
Conversation
|
Thanks for your pull request, @rainers! Bugzilla referencesYour PR doesn't reference any Bugzilla issue. If your PR contains non-trivial changes, please reference a Bugzilla issue or create a manual changelog. |
|
@rainers Is there any way to leverage compile-time information that main is @safe? E.g. albeit without relying on stuff from std.traits. Not that I follow everything in the current GC or your PR, but it looks like you are relying on run-time type information for some parts. I would think that if main is safe then you need to keep track of less information. I had previously asked on the forum about the impact of @safe on the GC as that would disallow access of pointers in unions and certain casts. The response I received was that you would still need to know at run-time what parts of the code are @safe or not and the run-time doesn't have information about @safe. However, if main is safe, then you would know for sure that these casts aren't available, etc. For instance, functions in the garbage collector could have a static if statement on isMainSafe that changes behavior at compile-time. |
There might be a little more information when knowing main is memory-safe (although I cannot think of any), but I don't think gurarantees are strong enough to really rely on for noticable optimizations:
|
|
@rainers I appreciate the reply. I had considered @trusted. My thinking was to treat the trusted code as safe. Now that I think on it, you would probably need an additional switch to make clear that the assumption is being made. On C calling conventions, my assumption was that extern(C) would typically be @System so it would not be in @safe code except through @trusted blocks. I had not considered static constructors/destructors, but they can also be labeled @safe (at least module ones, which I assume is what you meant), so I would imagine that they can also be checked if they are safe from the run-time, though I wouldn't know how. I had known that precise stack scanning was an issue for D, but wasn't sure how it would be handled. |
|
@rainers No. |
5689342 to
859867f
Compare
| * numBits - The total number of valid bits in the given bit array | ||
| * startBit - The initial start index to start searching | ||
| */ | ||
| this(const(size_t)* bitarr, size_t numBits, size_t startBit) @system |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hm.. this could be done I think with a default startBit arg instead of a new function.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't want to change the performance or inlinability of the other ctor.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Possibly the inlinability may be affected, but it is the ctor and not the hot path. But it made me pause a bit to see so much duplicated code :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The ctor can also be in a hot path. But you are right, it's not in the GC mark function. Actually, using the BitRange proved to be slower than testing single bits for possible pointers on my systems, so it's disabled via enum useBitRange = false;. @Jebbs measured improvements with the BitRange, though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, using the BitRange proved to be slower than testing single bits for possible pointers on my systems
I wrote the BitRange code to help me avoid the tedious task of finding all set bits in a bitset when checking for module cycles. I didn't spend really any time profiling, just used tricks I knew of, though it turned out to be faster than the previous method of foreaching over the bits and checking if they were set. Would be cool if we could improve it for your purposes. It probably depends highly on how dense the pointers are.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It probably depends highly on how dense the pointers are.
I guess so, too. The BitRange probably helps if it allows skipping a full cache line, but that doesn't seem to happen very often in our benchmarks.
src/gc/bits.d
Outdated
| return core.bitop.bt(data, i); | ||
| } | ||
|
|
||
| //pragma(inline,true) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was this supposed to be commented out?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IIRC inlining didn't always work, but this might be fixed in the meantime. I'll put the pragma back in.
|
Can't do a full review, as I'm not steeped in how this all works, but I did a cursory look from a code perspective. |
|
In wake of the recent work, we should improve the informativeness and reliability of GC benchmarks. @wilzbach sounds like a good project to put on your list? |
| } | ||
|
|
||
| pragma(inline,false) | ||
| void setPointerBitmap(void* p, size_t s, size_t allocSize, const TypeInfo ti, uint attr) nothrow |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It may be clearer during reading and less prone to mistakes by future maintainers if these two functions were distinguished by having different names rather than just having the order of their last two arguments swapped.
|
closing in favor of #2418 |

This is most #1603 without change of the GC interface.
Dynamic and associative arrays are scanned conservatively, though.