Skip to content

Conversation

@edi33416
Copy link
Contributor

No description provided.

@dlang-bot
Copy link
Contributor

Thanks for your pull request, @edi33416! We are looking forward to reviewing it, and you should be hearing from a maintainer soon.

Some tips to help speed things up:

  • smaller, focused PRs are easier to review than big ones

  • try not to mix up refactoring or style changes with bug fixes or feature enhancements

  • provide helpful commit messages explaining the rationale behind each change

Bear in mind that large or tricky changes may require multiple rounds of review and revision.

Please see CONTRIBUTING.md for more information.

Bugzilla references

Your PR doesn't reference any Bugzilla issue.

If your PR contains non-trivial changes, please reference a Bugzilla issue or create a manual changelog.

@edi33416 edi33416 force-pushed the rc_iallocator branch 2 times, most recently from f449552 to 7986102 Compare December 12, 2017 22:10
@andralex
Copy link
Member

I'll approve this to keep PR size under control. Subsequent work should add attributes to allocator interface appropriately.

@wilzbach
Copy link
Contributor

There are still three dub projects failing due the breaking changes you introduce, so we have to wait a bit anyhow. Also I feel like this PR is merged a bit too quickly. It still contains debug work and as such a big breaking API change, at least having a motivation in the changelog for why the IAllocator interface needs to be bloated with incRef/decRef would be nice.

@wilzbach
Copy link
Contributor

wilzbach commented Dec 13, 2017

There are still three dub projects failing due the breaking changes you introduce, so we have to wait a bit anyhow.

Happy merging & tagging a new release:

CC @s-ludwig

@andralex
Copy link
Member

There are still three dub projects failing due the breaking changes you introduce, so we have to wait a bit anyhow. Also I feel like this PR is merged a bit too quickly. It still contains debug work and as such a big breaking API change, at least having a motivation in the changelog for why the IAllocator interface needs to be bloated with incRef/decRef would be nice.

@edi33416 could you please insert a changelog before going on vacation?

@ghost
Copy link

ghost commented Dec 20, 2017

Dont forget to close https://issues.dlang.org/show_bug.cgi?id=15509

/// Ditto
nothrow @safe @nogc @property void theAllocator(IAllocator a)
nothrow @system @nogc
@property void theAllocator(RCIAllocator a)
Copy link
Member

@MartinNowak MartinNowak Dec 21, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it defined whether allocators can always free their backing memory on destruction, or whether they have to leak when there are still outstanding allocations?
I'm assuming the former as the bookkeeping overhead for the latter seems problematic.

If that's the case, making the theAllocator setter unsafe is quite a severe choice.
Sure you correctly force code that replaces the current allocator to be unsafe, but how could that code take any responsibility for all the allocations that were done with the previous theAllocator (or at least for that code to be reasonably auditable).

This would limit the safe Allocator usages to:

  • setting theAllocator once on startup
  • using local allocators for specific tasks
  • others???

But excluded (b/c crazily unsafe) those usages:

  • exchanging theAllocator after some time to optimize for the current workload
  • others???

Global allocators with finite lifetime are inherently unsafe. We should have a good answer to how we intend allocators to be used, before making this step.

As a side node, the old void theAllocator(IAllocator a) was already unsafe, as it could eliminate the last GC reference to the previous theAllocator. Allocations don't GC-pin their allocator and aren't usually GC tracked anyhow.

On a lighter note, this is the second special RC type (after RC Throwables), that's ending up in dlang before we're set on how to implement manual memory management in the language. Another class-based RC type instead of a polymorphic RC!(IAllocator). It's good to experiment, but it remains questionable whether std.experimental is the right place ;).
Anyhow, hopefully this won't cause too much maintenance effort down the road.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But excluded (b/c crazily unsafe) those usages:

  • exchanging theAllocator after some time to optimize for the current workload

What if the user wraps his allocator in a StatsCollector allocator that tracks the bytesUsed? This way he could safely change theAllocator

I'm thinking of something like:

alias SCAlloc = StatsCollector!(Mallocator, Options.bytesUsed);
SCAlloc statsCollectorAlloc;

// setup the allocator
() @trusted { theAllocator = allocatorObject(statsCollectorAlloc); }();
// do some work

// check if we can safely change the allocator
if (theAllocator.impl.bytesUsed == 0) { // change theAllocator }

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, good idea.
Haven't thought too well about how that would interact with possible compile-time lifetime checks (for RC et.al.), but keeping track of the outstanding bytes should allow for a cheap runtime safety check before exchanging theAllocator.
Would it be relevant whether the allocator set as theAllocator has been used beforehand? Would this be worthwhile to add as a static introspectable empty method to the allocator interfaces?

For processAllocator keeping track of bytes atomically might be somewhat expensive. Some clever per-thread accounting/caching could lower the overhead there.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be relevant whether the allocator set as theAllocator has been used beforehand?

Good question. The design is young, and at some point we'll need to answer this.

Would this be worthwhile to add as a static introspectable empty method to the allocator interfaces?

We already have empty: https://dlang.org/phobos/std_experimental_allocator.html#.IAllocator.empty

For processAllocator keeping track of bytes atomically might be somewhat expensive. Some clever per-thread accounting/caching could lower the overhead there.

This is tricky because the very notion of "empty" is evanescent for a shared allocator. You can't check for empty and then change the allocator - that's a race. We'd need some CAS-based mechanism. Let's discuss this further as needs arise.

@s-ludwig
Copy link
Member

The diet-ng PR has been merged and is avalable as version 1.4.4 now.

@wilzbach
Copy link
Contributor

wilzbach commented Jan 24, 2018

Thanks a lot @s-ludwig!
Argh it looks like we have to go through another wave :/

diet-ng 1.4.4: building configuration "library"...
taggedalgebraic 0.10.9: building configuration "library"...
eventcore 0.8.27: building configuration "epoll"...
stdx-allocator 2.77.0: building configuration "library"...
vibe-core : building configuration "epoll"...
../../.dub/packages/vibe-core-1.4.0-alpha.1/vibe-core/source/vibe/core/log.d(613,21): Deprecation: Built-in hex string literals are deprecated, use `std.conv.hexString` instead.
vibe-d:utils 0.8.3-alpha.2: building configuration "library"...
vibe-d:data 0.8.3-alpha.2: building configuration "library"...
vibe-d:crypto 0.8.3-alpha.2: building configuration "library"...
../../.dub/packages/vibe-d-0.8.3-alpha.2/vibe-d/crypto/vibe/crypto/cryptorand.d(12,8): Error: module stream is in file 'vibe/core/stream.d' which cannot be read
import path[0] = ../../.dub/packages/vibe-d-0.8.3-alpha.2/vibe-d/crypto

I can't reproduce this locally with 0.8.3-alpha.2 and vibe-core 1.4.0-alpha.1.

@wilzbach wilzbach force-pushed the rc_iallocator branch 2 times, most recently from 632c303 to 502dcdf Compare January 25, 2018 07:32
@wilzbach
Copy link
Contributor

@edi33416 you are in luck. Martin fixed the DUB regression this morning (dlang/dub#1350), so it looks like it's only dlang/ddox#194 (which lets dlang/dub fail) left.

@wilzbach wilzbach force-pushed the rc_iallocator branch 3 times, most recently from 2be85b6 to a1cb4b0 Compare January 25, 2018 12:02
@wilzbach
Copy link
Contributor

Hmm, the dub test doesn't want to pick up the new ddox version, e.g. :

diet-ng 1.4.3: building configuration "library"...
vibe-d:utils 0.8.2: building configuration "library"...

However, on my local machine (with verbose log)

> DC=/home/seb/dlang/dmd/generated/linux/release/64/dmd DUB=$(realpath bin/dub) CURR_DIR=$(pwd)/test bash test/ddox.sh
Configuring dependent ddox-project, deps:
Performing "ddox" build using dmd for x86_64.
ddox-project ~master: building configuration "library"...
dmd -o- -w -Xfdocs.json -Df__dummy.html -version=Have_ddox_project -Isource/ source/ddox_project.d -vcolumns
Using dub registry url 'https://code.dlang.org/'
Refreshing local packages (refresh existing: true)...
Looking for local package map at /var/lib/dub/packages/local-packages.json
Looking for local package map at /home/seb/.dub/packages/local-packages.json
Try to load local package map at /home/seb/.dub/packages/local-packages.json
Refreshing local packages (refresh existing: false)...
Looking for local package map at /var/lib/dub/packages/local-packages.json
Looking for local package map at /home/seb/.dub/packages/local-packages.json
Try to load local package map at /home/seb/.dub/packages/local-packages.json
  Found dependency vibe-d:web 0.8.3-alpha.1
    Found dependency vibe-d:http 0.8.3-alpha.1
      Found dependency vibe-d:tls 0.8.3-alpha.1
        Found dependency vibe-d:stream 0.8.3-alpha.1
          Found dependency vibe-d:core 0.8.3-alpha.1
            Found dependency vibe-d:utils 0.8.3-alpha.1
              Found dependency stdx-allocator 2.77.0
            Found dependency vibe-d:data 0.8.3-alpha.1
            Found dependency libevent 2.0.2+2.0.16
            Found dependency libasync 0.8.3
              Found dependency memutils 0.4.9
            Found dependency vibe-core 1.4.0-alpha.1
              Found dependency eventcore 0.8.27
                Found dependency taggedalgebraic 0.10.9
        Found dependency openssl 1.1.6+1.0.1g
        Found dependency botan 1.12.9
          Found dependency botan-math 1.0.3
      Found dependency vibe-d:crypto 0.8.3-alpha.1
      Found dependency vibe-d:inet 0.8.3-alpha.1
        Found dependency vibe-d:textfilter 0.8.3-alpha.1
      Found dependency diet-ng 1.4.4
  Found dependency hyphenate 1.1.1
  Found dependency libdparse 0.7.1
Using fixed selection vibe-d 0.8.3-alpha.1
Using fixed selection stdx-allocator 2.77.0

And even though the registry is down at the moment, the mirror picked up 0.16.8 correctly:

https://code-mirror.dlang.io/packages/ddox

Also at dlang/ci the entire dub cache is purged after every component has run.

Has someone an idea how to force the dub testsuite to use the latest ddox?

@wilzbach
Copy link
Contributor

Okay I can reproduce this with

dub fetch ddox --version=0.16.7
rm -rf ~/.dub/packages/ddox-0.16.8 

so it seems like we need to force dub to do an explicit fetch of ddox
However, the dub logic for runDdox doesn't anticipate fetching a new ddox version - it will use the latest, existing one if at least one version is found:

void runDdox(bool run, string[] generate_args = null)
{
	import std.process : browse;

	if (m_dryRun) return;

	// allow to choose a custom ddox tool
	auto tool = m_project.rootPackage.recipe.ddoxTool;
	if (tool.empty) tool = "ddox";

	auto tool_pack = m_packageManager.getBestPackage(tool, ">=0.0.0");
	if (!tool_pack) tool_pack = m_packageManager.getBestPackage(tool, "~master");
	if (!tool_pack) {
		logInfo("%s is not present, getting and storing it user wide", tool);
		tool_pack = fetch(tool, Dependency(">=0.0.0"), defaultPlacementLocation, FetchOptions.none);
	}

So in lack of better ideas, I will try to nuke ~/.dub with a PR to dlang/ci: dlang/ci#139

@wilzbach
Copy link
Contributor

So in lack of better ideas, I will try to nuke ~/.dub with a PR to dlang/ci: dlang/ci#139

Looks like that didn't work out either and 0.16.8 is still fetched.
I'm low on ideas - anyone with an idea?

CC @MartinNowak @s-ludwig

@MartinNowak
Copy link
Member

I manually deleted ddox on all slaves.
dlang/ci#139 (comment)

Seems to work.

@d-random-contributor
Copy link

Looks like processAllocator setter doesn't implement proper multithreading - it decrements reference before storing allocator. Also using setter before getter will still trigger initialization in getter.

@andralex
Copy link
Member

andralex commented Feb 5, 2018

cc @edi33416

@edi33416
Copy link
Contributor Author

edi33416 commented Feb 5, 2018

Ack. Will follow up with a PR to fix this.

@d-random-contributor thanks for pointing those out

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants