Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add betterC probing for performance and for applications without drun… #2753

Merged
merged 3 commits into from
Jan 10, 2024

Conversation

etcimon
Copy link
Contributor

@etcimon etcimon commented Dec 24, 2023

This improves performance and also allows me to compile a custom druntime with my application. (post-switches = [] in the ldc2.conf)

Copy link

github-actions bot commented Dec 24, 2023

✅ PR OK, no changes in deprecations or warnings

Total deprecations: 11

Total warnings: 0

Build statistics:

 statistics (-before, +after)
-executable size=5371736 bin/dub
-rough build time=62s
+executable size=5375832 bin/dub
+rough build time=63s
Full build output
DUB version 1.35.1, built on Jan  6 2024
LDC - the LLVM D compiler (1.36.0):
  based on DMD v2.106.1 and LLVM 17.0.6
  built with LDC - the LLVM D compiler (1.36.0)
  Default target: x86_64-unknown-linux-gnu
  Host CPU: znver3
  http://dlang.org - http://wiki.dlang.org/LDC


  Registered Targets:
    aarch64     - AArch64 (little endian)
    aarch64_32  - AArch64 (little endian ILP32)
    aarch64_be  - AArch64 (big endian)
    amdgcn      - AMD GCN GPUs
    arm         - ARM
    arm64       - ARM64 (little endian)
    arm64_32    - ARM64 (little endian ILP32)
    armeb       - ARM (big endian)
    avr         - Atmel AVR Microcontroller
    bpf         - BPF (host endian)
    bpfeb       - BPF (big endian)
    bpfel       - BPF (little endian)
    hexagon     - Hexagon
    lanai       - Lanai
    loongarch32 - 32-bit LoongArch
    loongarch64 - 64-bit LoongArch
    mips        - MIPS (32-bit big endian)
    mips64      - MIPS (64-bit big endian)
    mips64el    - MIPS (64-bit little endian)
    mipsel      - MIPS (32-bit little endian)
    msp430      - MSP430 [experimental]
    nvptx       - NVIDIA PTX 32-bit
    nvptx64     - NVIDIA PTX 64-bit
    ppc32       - PowerPC 32
    ppc32le     - PowerPC 32 LE
    ppc64       - PowerPC 64
    ppc64le     - PowerPC 64 LE
    r600        - AMD GPUs HD2XXX-HD6XXX
    riscv32     - 32-bit RISC-V
    riscv64     - 64-bit RISC-V
    sparc       - Sparc
    sparcel     - Sparc LE
    sparcv9     - Sparc V9
    spirv32     - SPIR-V 32-bit
    spirv64     - SPIR-V 64-bit
    systemz     - SystemZ
    thumb       - Thumb
    thumbeb     - Thumb (big endian)
    ve          - VE
    wasm32      - WebAssembly 32-bit
    wasm64      - WebAssembly 64-bit
    x86         - 32-bit X86: Pentium-Pro and above
    x86-64      - 64-bit X86: EM64T and AMD64
    xcore       - XCore
   Upgrading project in /home/runner/work/dub/dub/
    Starting Performing "release" build using /opt/hostedtoolcache/dc/ldc2-1.36.0/x64/ldc2-1.36.0-linux-x86_64/bin/ldc2 for x86_64.
    Building dub 1.36.0-beta.1+commit.30.ga4abc842: building configuration [application]
/opt/hostedtoolcache/dc/ldc2-1.36.0/x64/ldc2-1.36.0-linux-x86_64/bin/../import/std/algorithm/iteration.d(475,42): Deprecation: function `dub.dub.getRegistryPackageSupplier` is deprecated - This function wasn't intended for public use - open an issue with Dub if you need it
source/dub/dub.d(67,57):        instantiated from here: `map!(immutable(string)[])`
/opt/hostedtoolcache/dc/ldc2-1.36.0/x64/ldc2-1.36.0-linux-x86_64/bin/../import/std/algorithm/iteration.d(582,19): Deprecation: function `dub.dub.getRegistryPackageSupplier` is deprecated - This function wasn't intended for public use - open an issue with Dub if you need it
/opt/hostedtoolcache/dc/ldc2-1.36.0/x64/ldc2-1.36.0-linux-x86_64/bin/../import/std/algorithm/iteration.d(479,16):        instantiated from here: `MapResult!(getRegistryPackageSupplier, immutable(string)[])`
source/dub/dub.d(67,57):        instantiated from here: `map!(immutable(string)[])`
/opt/hostedtoolcache/dc/ldc2-1.36.0/x64/ldc2-1.36.0-linux-x86_64/bin/../import/std/algorithm/iteration.d(594,23): Deprecation: function `dub.dub.getRegistryPackageSupplier` is deprecated - This function wasn't intended for public use - open an issue with Dub if you need it
/opt/hostedtoolcache/dc/ldc2-1.36.0/x64/ldc2-1.36.0-linux-x86_64/bin/../import/std/algorithm/iteration.d(479,16):        instantiated from here: `MapResult!(getRegistryPackageSupplier, immutable(string)[])`
source/dub/dub.d(67,57):        instantiated from here: `map!(immutable(string)[])`
source/dub/internal/configy/Exceptions.d(248,27): Deprecation: `@safe` function `formatMessage` calling `formattedWrite`
/opt/hostedtoolcache/dc/ldc2-1.36.0/x64/ldc2-1.36.0-linux-x86_64/bin/../import/std/format/write.d(537,34):        which calls `std.format.spec.FormatSpec!char.FormatSpec.writeUpToNextSpec!(void delegate(in char[]) @safe).writeUpToNextSpec`
/opt/hostedtoolcache/dc/ldc2-1.36.0/x64/ldc2-1.36.0-linux-x86_64/bin/../import/std/format/spec.d(258,33):        which wouldn't be `@safe` because of:
/opt/hostedtoolcache/dc/ldc2-1.36.0/x64/ldc2-1.36.0-linux-x86_64/bin/../import/std/format/spec.d(258,33):        scope variable `this` assigned to non-scope parameter `e` calling `put`
source/dub/internal/configy/Exceptions.d(250,27): Deprecation: `@safe` function `formatMessage` calling `formattedWrite`
/opt/hostedtoolcache/dc/ldc2-1.36.0/x64/ldc2-1.36.0-linux-x86_64/bin/../import/std/format/write.d(537,34):        which calls `std.format.spec.FormatSpec!char.FormatSpec.writeUpToNextSpec!(void delegate(in char[]) @safe).writeUpToNextSpec`
/opt/hostedtoolcache/dc/ldc2-1.36.0/x64/ldc2-1.36.0-linux-x86_64/bin/../import/std/format/spec.d(258,33):        which wouldn't be `@safe` because of:
/opt/hostedtoolcache/dc/ldc2-1.36.0/x64/ldc2-1.36.0-linux-x86_64/bin/../import/std/format/spec.d(258,33):        scope variable `this` assigned to non-scope parameter `e` calling `put`
source/dub/internal/configy/Exceptions.d(283,27): Deprecation: `@safe` function `formatMessage` calling `formattedWrite`
/opt/hostedtoolcache/dc/ldc2-1.36.0/x64/ldc2-1.36.0-linux-x86_64/bin/../import/std/format/write.d(537,34):        which calls `std.format.spec.FormatSpec!char.FormatSpec.writeUpToNextSpec!(void delegate(in char[]) @safe).writeUpToNextSpec`
/opt/hostedtoolcache/dc/ldc2-1.36.0/x64/ldc2-1.36.0-linux-x86_64/bin/../import/std/format/spec.d(258,33):        which wouldn't be `@safe` because of:
/opt/hostedtoolcache/dc/ldc2-1.36.0/x64/ldc2-1.36.0-linux-x86_64/bin/../import/std/format/spec.d(258,33):        scope variable `this` assigned to non-scope parameter `e` calling `put`
source/dub/internal/configy/Exceptions.d(286,27): Deprecation: `@safe` function `formatMessage` calling `formattedWrite`
/opt/hostedtoolcache/dc/ldc2-1.36.0/x64/ldc2-1.36.0-linux-x86_64/bin/../import/std/format/write.d(537,34):        which calls `std.format.spec.FormatSpec!char.FormatSpec.writeUpToNextSpec!(void delegate(in char[]) @safe).writeUpToNextSpec`
/opt/hostedtoolcache/dc/ldc2-1.36.0/x64/ldc2-1.36.0-linux-x86_64/bin/../import/std/format/spec.d(258,33):        which wouldn't be `@safe` because of:
/opt/hostedtoolcache/dc/ldc2-1.36.0/x64/ldc2-1.36.0-linux-x86_64/bin/../import/std/format/spec.d(258,33):        scope variable `this` assigned to non-scope parameter `e` calling `put`
source/dub/internal/configy/Exceptions.d(323,31): Deprecation: `@safe` function `formatMessage` calling `formattedWrite`
/opt/hostedtoolcache/dc/ldc2-1.36.0/x64/ldc2-1.36.0-linux-x86_64/bin/../import/std/format/write.d(537,34):        which calls `std.format.spec.FormatSpec!char.FormatSpec.writeUpToNextSpec!(void delegate(in char[]) @safe).writeUpToNextSpec`
/opt/hostedtoolcache/dc/ldc2-1.36.0/x64/ldc2-1.36.0-linux-x86_64/bin/../import/std/format/spec.d(258,33):        which wouldn't be `@safe` because of:
/opt/hostedtoolcache/dc/ldc2-1.36.0/x64/ldc2-1.36.0-linux-x86_64/bin/../import/std/format/spec.d(258,33):        scope variable `this` assigned to non-scope parameter `e` calling `put`
source/dub/internal/configy/Exceptions.d(325,31): Deprecation: `@safe` function `formatMessage` calling `formattedWrite`
/opt/hostedtoolcache/dc/ldc2-1.36.0/x64/ldc2-1.36.0-linux-x86_64/bin/../import/std/format/write.d(537,34):        which calls `std.format.spec.FormatSpec!char.FormatSpec.writeUpToNextSpec!(void delegate(in char[]) @safe).writeUpToNextSpec`
/opt/hostedtoolcache/dc/ldc2-1.36.0/x64/ldc2-1.36.0-linux-x86_64/bin/../import/std/format/spec.d(258,33):        which wouldn't be `@safe` because of:
/opt/hostedtoolcache/dc/ldc2-1.36.0/x64/ldc2-1.36.0-linux-x86_64/bin/../import/std/format/spec.d(258,33):        scope variable `this` assigned to non-scope parameter `e` calling `put`
source/dub/internal/configy/Exceptions.d(332,31): Deprecation: `@safe` function `formatMessage` calling `formattedWrite`
/opt/hostedtoolcache/dc/ldc2-1.36.0/x64/ldc2-1.36.0-linux-x86_64/bin/../import/std/format/write.d(537,34):        which calls `std.format.spec.FormatSpec!char.FormatSpec.writeUpToNextSpec!(void delegate(in char[]) @safe).writeUpToNextSpec`
/opt/hostedtoolcache/dc/ldc2-1.36.0/x64/ldc2-1.36.0-linux-x86_64/bin/../import/std/format/spec.d(258,33):        which wouldn't be `@safe` because of:
/opt/hostedtoolcache/dc/ldc2-1.36.0/x64/ldc2-1.36.0-linux-x86_64/bin/../import/std/format/spec.d(258,33):        scope variable `this` assigned to non-scope parameter `e` calling `put`
source/dub/internal/configy/Exceptions.d(335,31): Deprecation: `@safe` function `formatMessage` calling `formattedWrite`
/opt/hostedtoolcache/dc/ldc2-1.36.0/x64/ldc2-1.36.0-linux-x86_64/bin/../import/std/format/write.d(537,34):        which calls `std.format.spec.FormatSpec!char.FormatSpec.writeUpToNextSpec!(void delegate(in char[]) @safe).writeUpToNextSpec`
/opt/hostedtoolcache/dc/ldc2-1.36.0/x64/ldc2-1.36.0-linux-x86_64/bin/../import/std/format/spec.d(258,33):        which wouldn't be `@safe` because of:
/opt/hostedtoolcache/dc/ldc2-1.36.0/x64/ldc2-1.36.0-linux-x86_64/bin/../import/std/format/spec.d(258,33):        scope variable `this` assigned to non-scope parameter `e` calling `put`
     Linking dub
STAT:statistics (-before, +after)
STAT:executable size=5375832 bin/dub
STAT:rough build time=63s

@rikkimax
Copy link
Contributor

Duplicate of: #2699

@etcimon
Copy link
Contributor Author

etcimon commented Dec 24, 2023

My solution involves minor changes and reverts to old behaviour, easier to approve.

@@ -183,18 +183,32 @@ interface Compiler {
import dub.compilers.utils : generatePlatformProbeFile, readPlatformJsonProbe;
import std.string : format, strip;

auto fil = generatePlatformProbeFile();
NativePath fil = generatePlatformProbeFile!true();
auto result_betterC = execute(compiler_binary ~ args ~ "-betterC" ~ fil.toNativeString());
Copy link
Contributor

Choose a reason for hiding this comment

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

-betterC is called something else with GDC ,-f-no-druntime or something like that.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Seems to be -fno-druntime

Comment on lines 275 to 278
enum moduleInfo = betterC ? q{
module object;
alias string = const(char)[];
alias size_t = uint;
template _d_arrayappendcTXImpl(Tarr : T[], T){
ref Tarr _d_arrayappendcTX(return ref scope Tarr px, size_t n) @trusted pure nothrow{return px;}
}
const(char)[][] _d_arrayappendcTX(return scope ref const(char)[][] px, size_t n){return px;}
Tarr _d_arrayappendT(Tarr : T[], T)(return ref scope Tarr x, scope Tarr y){return x;}
} : q{
module dub_platform_probe;
};
Copy link
Member

Choose a reason for hiding this comment

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

I'm a bit concerned about this part, as it seems to be specific to the current state of BetterC. Future improvements might make this out of date. Am I right that the problem arises because the platform probe has a dependency on the runtime ? Couldn't we achieve something similar with a sufficiently sized static array ?

Copy link
Contributor Author

@etcimon etcimon Jan 3, 2024

Choose a reason for hiding this comment

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

It's the string[] appender running as CTFE that calls the runtime as a noop, if there's any improvements we would be removing some definitions and that's pretty much it. Either way if anything breaks it'll show a warning and fallback to using the runtime (through the bool retry in the catch)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The CTFE doesn't support using static storage either, you have to use the GC to create an allocation and then you can reference it in scope

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I managed to remove the declarations by using only pragma(msg, ) and formatting the string at the end

@etcimon etcimon force-pushed the probe_with_betterc branch 4 times, most recently from 7d35ef2 to a342d7e Compare January 4, 2024 01:04
@etcimon etcimon force-pushed the probe_with_betterc branch from a342d7e to 2250725 Compare January 4, 2024 03:40
@etcimon etcimon requested a review from Geod24 January 4, 2024 23:28
@@ -16,6 +16,7 @@ __dummy.html
/bin/dub-test-library
/bin/libdub.a
/bin/dub-*
/bin/dub.*
Copy link
Member

Choose a reason for hiding this comment

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

Unrelated

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's a minor annoyance when using vscode source control on windows, I was thinking it didn't require mention, nor its own pull request.

Copy link
Member

Choose a reason for hiding this comment

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

What artifacts does vscode generate ? We can keep it in this PR, I just could not tell where it's coming from.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is for the dub.exe and dub.pdb files that are generated when building under windows.

source/dub/compilers/compiler.d Show resolved Hide resolved
@Geod24
Copy link
Member

Geod24 commented Jan 5, 2024

Just to be sure I follow: Do we need the -betterC flag if we make it -betterC-compliant ? As in, if you get it to a point it does not pull anything from the runtime, the flag becomes superfluous, doesn't it ?

@rikkimax
Copy link
Contributor

rikkimax commented Jan 5, 2024

Just to be sure I follow: Do we need the -betterC flag if we make it -betterC-compliant ? As in, if you get it to a point it does not pull anything from the runtime, the flag becomes superfluous, doesn't it ?

No, it doesn't.

You will still be linking against druntime, and that has cost.

@etcimon
Copy link
Contributor Author

etcimon commented Jan 5, 2024

The probePlatform routine takes ~25ms (vs ~38ms previously) for me using a StopWatch when building with these improvements. It's now also compatible with projects that don't include druntime.

If I benchmark only the first run on windows arch x86_64, it goes from 52ms to 24ms

@etcimon
Copy link
Contributor Author

etcimon commented Jan 5, 2024

On dmd removing the -betterC flag improves it to 18ms, but with ldc it worsens it to 40ms.

@Geod24
Copy link
Member

Geod24 commented Jan 5, 2024

You will still be linking against druntime, and that has cost.

Why do we need to link ?

@etcimon
Copy link
Contributor Author

etcimon commented Jan 5, 2024

It wouldn't link, it doesn't write an object file, compile flag -o-. It's mostly dmd.dinterpret in the compiler doing most of the work and returning after.

@Geod24
Copy link
Member

Geod24 commented Jan 5, 2024

It's mostly dmd.dinterpret in the compiler doing most of the work and returning after.

So why is -betterC relevant here ? That's what I'm confused about. I would like to solve your issue, but I'm not sure I fully understand it.

@etcimon
Copy link
Contributor Author

etcimon commented Jan 5, 2024

Originally it's because this project https://github.com/etcimon/libwasm implements its own druntime and for it you must remove the includes in ldc2.conf, but probing fails on that configuration if it depends on druntime.

@Geod24
Copy link
Member

Geod24 commented Jan 5, 2024

but probing fails on that configuration if it depends on druntime.

I assume that probing fails because it tries to import druntime, rather than link it ?

@etcimon
Copy link
Contributor Author

etcimon commented Jan 5, 2024

It complains that there is no module object

@Geod24
Copy link
Member

Geod24 commented Jan 5, 2024

@kinke : Any chance you could have a look at this ? I think the use case is good, but I would like to make sure it keeps on working with newer versions of DMD/LDC with minimal maintenance.

@etcimon
Copy link
Contributor Author

etcimon commented Jan 5, 2024

So why is -betterC relevant here ?

It works without -betterC, but it does help with both performance and guarantees.

@etcimon
Copy link
Contributor Author

etcimon commented Jan 8, 2024

Are we waiting on @kinke for a follow-up?

@kinke
Copy link
Contributor

kinke commented Jan 8, 2024

AFAICT after a quick glance, the main change here is that the generated probe module becomes the special object module, only defining the string alias (not even size_t), so that the (fat) druntime one isn't imported. -betterC then shouldn't really make a difference, as its effects should be enabled automatically without TypeInfo class etc. in object.

While such a minimalistic, fully self-contained D module is surely fast to analyze with -o- and working for ~all exotic targets too, the cost is the ugly duplication in source/dub/platform.d. I guess that could be improved though by post-processing the existing string, e.g., replacing ret ~= <literal>; by pragma(msg, ´ <literal>´); and stripping off string[] ret; and return ret;.

@etcimon
Copy link
Contributor Author

etcimon commented Jan 9, 2024

I guess that could be improved though by post-processing the existing string

The post-processing using regex, matchAll and replace makes it impossible to evaluate the string with ctfe, but I doubt this would make it slower.

@etcimon etcimon force-pushed the probe_with_betterc branch from 169a3cc to fece411 Compare January 9, 2024 00:37
@etcimon etcimon force-pushed the probe_with_betterc branch from 1447625 to 01a8156 Compare January 9, 2024 00:53
@etcimon
Copy link
Contributor Author

etcimon commented Jan 9, 2024

nvm I got it working in ctfe

Copy link
Member

@Geod24 Geod24 left a comment

Choose a reason for hiding this comment

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

Looks pretty nice, just a few nits. I don't know if you want/can add a test to avoid a regression, I'm happy to merge as-is otherwise once the nits have been addressed.

Comment on lines 191 to 193
BuildPlatform build_platform;

auto build_platform = readPlatformJsonProbe(result.output);
build_platform = readPlatformSDLProbe(result.output);
Copy link
Member

Choose a reason for hiding this comment

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

Merge those two lines ?

if (ver.empty) {
logWarn(`Could not probe the compiler version for "%s". ` ~
`Toolchain requirements might be ineffective`, build_platform.compiler);
`Toolchain requirements might be ineffective`, build_platform.compiler);
Copy link
Member

Choose a reason for hiding this comment

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

Revert

@@ -268,78 +268,103 @@ private enum probeEndMark = "__dub_probe_end__";
*/
NativePath generatePlatformProbeFile()
{

Copy link
Member

Choose a reason for hiding this comment

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

Revert

module object;
alias string = const(char)[];
};

// try to not use phobos in the probe to avoid long import times
Copy link
Member

Choose a reason for hiding this comment

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

I would also modify the comment so the next person knows the platform probe should not rely on the runtime to make your use case possible.

@etcimon
Copy link
Contributor Author

etcimon commented Jan 9, 2024

Should I squash it?

@Geod24 Geod24 merged commit 509beb8 into dlang:master Jan 10, 2024
30 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants