November 12, 2021
On Fri, Nov 12, 2021 at 10:14:28PM +0100, Timon Gehr via Digitalmars-d wrote:
> On 12.11.21 18:44, H. S. Teoh wrote:
> > Yes.  So actually, this*could*  be made to work if the RC payload is only allowed to be allocated from an RC allocator.  The allocator would allocate n+8 bytes, for example, and return a pointer to offset 8 of the allocated block, which is cast to whatever type/qualifier(s) needed.  Offset 0 would be the reference count. The copy ctor would access the reference count as *(ptr-8), which is technically outside the const/immutable/whatever payload.  When the ref count reaches 0, the allocator knows to deallocate the block starting from (ptr-8), which is the start of the actual allocation.
> 
> You still need language support. Reaching mutable data through an immutable pointer violates transitivity assumptions.

Aside from the technicalities of storing the refcount in the machine word preceding the allocated block, one could imagine this as looking up (and updating) state in a global AA using the address of the immutable ref.

Definitely impure, though, 'cos if we want to remain consistent with the global AA analogy, we have to consider the refcount as global state, so we cannot do this kind of refcounting in pure code.


T

-- 
Life begins when you can spend your spare time programming instead of watching television. -- Cal Keegan
November 12, 2021
On 2021-11-12 16:14, Timon Gehr wrote:
> On 12.11.21 18:44, H. S. Teoh wrote:
>> Yes.  So actually, this*could*  be made to work if the RC payload is
>> only allowed to be allocated from an RC allocator.  The allocator would
>> allocate n+8 bytes, for example, and return a pointer to offset 8 of the
>> allocated block, which is cast to whatever type/qualifier(s) needed.
>> Offset 0 would be the reference count.  The copy ctor would access the
>> reference count as *(ptr-8), which is technically outside the
>> const/immutable/whatever payload.  When the ref count reaches 0, the
>> allocator knows to deallocate the block starting from (ptr-8), which is
>> the start of the actual allocation.
> 
> You still need language support. Reaching mutable data through an immutable pointer violates transitivity assumptions.

Indeed, but not indirectly. You can soundly access a pointer to mutable data if you use the immutable pointer as a key in a global hashtable.
November 12, 2021
On Fri, Nov 12, 2021 at 09:25:23PM +0000, russhy via Digitalmars-d wrote:
> On Thursday, 11 November 2021 at 09:15:54 UTC, Atila Neves wrote:
> 
> > > Who, using a SYSTEMS language, should not have a reason to care about their memory?
> > 
> > Me, ~99.9% of the time.
> > 
> 
> 
> This explains a lot and why D is stuck with a miserable GC

It depends on what the code is trying to do.  When I'm using D as a superior shell scripting language, yeah I couldn't care less about the intricacies of memory allocation.

If I'm writing performance sensitive code, though, which does happen quite often, then I *do* care about minimizing allocations and/or outright eliminating allocation from my inner loops.

It's about taking care of resource usage *where it matters*. There is no point optimizing the heck out of a hello world program: that's just a total waste of time. Save your efforts for when you're writing performance critical code.

This is why I also say, why are people so hung up about the GC?  If your inner loops have performance problems with the GC, then rewrite it as @nogc, use malloc/free/whatever it takes to make it faster.  The rest of the program can still use the GC -- there's no reason why I shouldn't just allocate away when I'm rendering, say, the splash screen and loading resource files on program startup, and let the GC clean up for me. It's much faster to write and I don't waste time micro-optimizing code that only runs once anyway.  I'd rather save my energy for when the program starts doing real work and needs to get it done fast -- that's when I pull out @nogc, GC.disable, malloc/free, etc..  Only the actual bottlenecks (as measured by an actual profiler) need to do this; the rest of the code that only runs once in a while don't matter, nobody will care whether it uses GC or not.  Life is too short to fuss over code that isn't even relevant to performance in the big picture.


T

-- 
The diminished 7th chord is the most flexible and fear-instilling chord. Use it often, use it unsparingly, to subdue your listeners into submission!
November 12, 2021
On Friday, 12 November 2021 at 22:10:22 UTC, H. S. Teoh wrote:

> Life is too short to fuss over code that isn't even relevant to performance in the big picture.

Life is too short to wait on programs that have no reason to be slow. If you're "rendering splash screen while loading resources", you're most likely doing something wrong. Your program should've been on screen and interactive ages ago. Granted, there can be exceptions (like slow storage), but those are very, very rare. Visual Studio has no business taking 8 seconds to load just to show its start screen. But it does. In a team of 50 people, starting it up twice a day, it wastes 57 man-hours a year. In other words, VS is a worker that comes in 7 days a year with full salary and amenities, to do absolutely nothing.

"The rest of the code that only runs once in a while don't matter" is an anachronism that needs to die, with fire. Whether you run once or a hundred times, you bloody well should run as fast as you possibly can, because there's always someone (or something) waiting on you! Including your own CPU. At the very least, it's just irresponsible to run unnecessarily slow.

Scripts for your own self - fine, leave 'em as slow as you're willing to suffer through. But please don't inflict your sloth-ness on the rest of the world ;)
November 12, 2021

On Friday, 12 November 2021 at 21:25:23 UTC, russhy wrote:

>

On Thursday, 11 November 2021 at 09:15:54 UTC, Atila Neves wrote:

> >

Who, using a SYSTEMS language, should not have a reason to care about their memory?

Me, ~99.9% of the time.

This explains a lot and why D is stuck with a miserable GC

We were waiting on your patches.

November 12, 2021
On Friday, 12 November 2021 at 22:10:22 UTC, H. S. Teoh wrote:
> This is why I also say, why are people so hung up about the GC?  If your inner loops have performance problems with the GC, then rewrite it as @nogc, use malloc/free/whatever it takes to make it faster.

If you have a large scannable heap then scanning will pollute the shared memory caches. Unless your scanning code use load/save instructions that bypass the caches. So in essence GC collection affects the whole system, also @nogc code. Another downside of imprecise scanning is that you need to zero out memory in order to make sure memory gets freed.

Now, if you tied a fully precise GC to a smaller unit, like a computation, then you could get better performance than other schemes since you often could just drop the whole heap without scanning when the computation is complete.

But the chosen path for D does not allow this, as of today, which does give people reason to wonder about the future direction for language evolution.


November 12, 2021

On Friday, 12 November 2021 at 23:05:44 UTC, deadalnix wrote:

>

On Friday, 12 November 2021 at 21:25:23 UTC, russhy wrote:

>

On Thursday, 11 November 2021 at 09:15:54 UTC, Atila Neves wrote:

> >

Who, using a SYSTEMS language, should not have a reason to care about their memory?

Me, ~99.9% of the time.

This explains a lot and why D is stuck with a miserable GC

We were waiting on your patches.

You are advocating in favor of the GC, you should be the one to come with patches

I'm advocating for allocator driven APIs, but that would involve whover who started std.experimental.allocator to finish his work instead of trying to start bunch of new ones, including versioning what's not yet finished

November 13, 2021
On Friday, 12 November 2021 at 22:09:28 UTC, Andrei Alexandrescu wrote:
> On 2021-11-12 16:14, Timon Gehr wrote:
>> You still need language support. Reaching mutable data through an immutable pointer violates transitivity assumptions.
>
> Indeed, but not indirectly. You can soundly access a pointer to mutable data if you use the immutable pointer as a key in a global hashtable.

I guess the question reduces to: what is the simplest thing you can do to a pointer that will make the compiler forget its provenance?

Adding an offset is clearly not enough. Casting it to an integer, taking its hash, and using that hash to look up a value in an associative array is probably *more* than enough. Is there something in between that's "just right"?

One possibility is casting the pointer to an integer, and then immediately casting it back:

    immutable(int)* p;
    size_t n = cast(size_t) (p - 1);
    int* q = cast(int*) n;
    *q = 123;

Assume we know, somehow, that the memory location pointed by q is allocated and contains a mutable int. Does the mutation in the final line have undefined behavior?

The answer depends on whether integers have provenance or not--a question which remains unsettled in the world of C and C++. [1] If we decide that integers should *not* have provenance in D, then the above code is valid, and we do not need to add any new features to the type system to support it.

The downsides of this approach are:

  1) Understanding and maintaining code that relies on obscure language rules like this is really difficult.
  2) Existing compiler backends (GCC, LLVM) don't always handle code like this correctly, even in C. (See linked article.)

[1] https://www.ralfj.de/blog/2020/12/14/provenance.html
November 12, 2021
On Fri, Nov 12, 2021 at 10:47:56PM +0000, Stanislav Blinov via Digitalmars-d wrote:
> On Friday, 12 November 2021 at 22:10:22 UTC, H. S. Teoh wrote:
> 
> > Life is too short to fuss over code that isn't even relevant to performance in the big picture.
> 
> Life is too short to wait on programs that have no reason to be slow. If you're "rendering splash screen while loading resources", you're most likely doing something wrong. Your program should've been on screen and interactive ages ago. Granted, there can be exceptions (like slow storage), but those are very, very rare. Visual Studio has no business taking 8 seconds to load just to show its start screen.

If you're waiting 8 full seconds, that's a sign that something is wrong with your performance. ;-)  Incidentally, this is why I don't bother with IDEs; most of them are bloated for no reason and take ages to load "resources" who knows for what. I could already be typing code in Vim and could already be compiling the first draft by the time they finish "starting up".  That's not what I was talking about, though.  I was talking about programs that load in 1 second or less -- in which case trying to optimize startup code is a waste of time.  If you're taking 8 seconds to start up, that *is* a performance problem and you should be optimizing that!


> But it does. In a team of 50 people, starting it up twice a day, it wastes 57 man-hours a year. In other words, VS is a worker that comes in 7 days a year with full salary and amenities, to do absolutely nothing.

I agree, that's why I don't bother with IDEs.  Especially not those that need to be started up every day.  I mean, who has the time to wait for that?!  I keep my Vim sessions in GNU Screen for months, if not years, at a time, and as soon as I sit down at my desk I can continue where I left off yesterday immediately.


> "The rest of the code that only runs once in a while don't matter" is an anachronism that needs to die, with fire. Whether you run once or a hundred times, you bloody well should run as fast as you possibly can, because there's always someone (or something) waiting on you! Including your own CPU. At the very least, it's just irresponsible to run unnecessarily slow.

Given that I run my Vim sessions for years at a time, startup time *is* completely irrelevant to me. :-D  If your program is such that people have to constantly restart it, something is bogonous with your design and you *should* consider scrapping it and doing it better.

But you took what I said completely out of context. I was talking about optimizing the code where the profiler indicates an actual bottleneck; 90% of your code is not part of a bottleneck and therefore "optimizing" it prematurely is a waste of time, not to mention it makes for needlessly unreadable and unmaintainable code.  (An 8-second startup time *is* a bottleneck, BTW. Just so we're on the same page.)  If code that isn't part of a bottleneck is allocating and waiting for GC collection, who cares?? It's not the bottleneck, you should be spending your time fixing actual bottlenecks instead.  That's my point.


> Scripts for your own self - fine, leave 'em as slow as you're willing to suffer through. But please don't inflict your sloth-ness on the rest of the world ;)

Honestly, just about *anything* written in D runs faster than any shell script (except perhaps for the most trivial of things like hello world programs -- actually, even those run faster in D :-P).  Just the very act of writing it in D has already given me a major speed boost, I'm not gonna sweat over squeezing microseconds out of it unless I'm also planning to run it in a tight loop 1,000,000 times per second.

And seriously, "ultra-optimized" code wastes more time than it saves, because it makes code unreadable and unmaintainable, and the poor fool who inherits your code will be wasting so much more time trying to understand just what the heck your code is trying to do than if you had written it in an obvious way that's slightly slower but doesn't really matter anyway because it's not even part of any bottleneck.  All those hours added up is a lot of wasted programmer wages which could have been spent actually adding business value, like y'know implementing features and fixing bugs instead of pulling out your hair trying to understand just what the code is doing.

Do the rest of the world a favor by keeping such unreadable code out of your codebase except where it's actually *necessary*.


T

-- 
Be in denial for long enough, and one day you'll deny yourself of things you wish you hadn't.
November 13, 2021

On Saturday, 13 November 2021 at 01:12:32 UTC, H. S. Teoh wrote:

>

On Fri, Nov 12, 2021 at 10:47:56PM

> >

Life is too short to fuss over code that isn't even relevant to performance in the big picture.

Although you spoke very well, you took d into the big hole.
If there is always GC, I believe that d has no future.
Everybody's gone.