aclysma / profiling

Provides a very thin abstraction over instrumented profiling crates like puffin, optick, tracy, and superluminal-perf.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Mutually exclusive features are present in profiling-procmacros

pacak opened this issue · comments

commented

According to https://github.com/rust-lang/cargo/blob/master/src/doc/src/reference/features.md#feature-unification features should be additive:

A consequence of this is that features should be additive. That is, enabling a feature should not disable functionality, and it should usually be safe to enable any combination of features.

while profiling-macros contains several different features that add one impl_block each which results in odd compilation errors when several are enabled. This makes it hard to use tools such as udeps amongst other things listed in a link I gave.

The guidance in the linked document does not apply to this crate. Published crates should never ship with any of these features enabled. They should only be enabled during local development.

This avoids the stated concern of “coordinating all uses of the package in the dependency graph to cooperate to avoid enabling them together”

BTW using more than one profiler at a time is likely to negatively impact accuracy of the resulting data.

Can you be more specific about why this is a problem with udeps? Have you tried ignoring this crate? (https://github.com/est31/cargo-udeps#ignoring-some-of-the-dependencies)

commented

When used with --all-features to deal with local features

cargo +nightly udeps --workspace --all-targets --all-features

profiling-procmacros fails to compile with

44  | / fn impl_block(
45  | |     body: &syn::Block,
46  | |     _instrumented_function_name: &str,
47  | | ) -> syn::Block {
...   |
54  | |     }
55  | | }
    | |_- previous definition of the value `impl_block` here
...
101 | / fn impl_block(
102 | |     body: &syn::Block,
103 | |     instrumented_function_name: &str,
104 | | ) -> syn::Block {
...   |
112 | |     }
113 | | }
    | |_^ `impl_block` redefined here
    |
    = note: `impl_block` must be defined only once in the value namespace of this module

Ignoring dependency that pulls in profiling-procmacro is not an option because a bunch of other code depends on it though other dependencies. There are other workarounds but they come with their own annoyances.

The only idea I've come up with is have a feature that turns off all the other features. But that's also recommended against in the same doc. Or I guess have some sort of "priority" so the logic conceptually is if (profiler_x) { ... } else if (profiler_y) { ... } else if ... but that's just a more subtle way of implementing a feature in a non-additive way. And if someone accidentally enables two profilers, it will silently fail, whereas currently they will get compile errors. But, it means all combinations of feature flags will compile.

(My main concern is not wanting to maintain 2^n permutations of supported ways to use the library, and keeping the library tiny enough to not be off-putting for people to want to use it, since this is the sort of crate that really benefits from being more widely used.)

We do have a feature type-check that is meant for CI - it validates all profiling usage would compile if a profiler was enabled. I suppose we could use that also as a "disable all" flag as well although I would lean towards making "disable all" a separate feature, if we have it at all.

commented

Having "disable all" flag goes against the same recommendations unfortunately.

In the ideal world this would be N separate crates: as you said yourself having several profilers enabled at the same time makes little sense, each crate could have an "enabled" feature which would allow you to switch profiling on and off.

Next best approach I think would be to generate a common instrumentation block with all the profilers nested into each other - layers corresponding to each profiler are always present but when disabled it's just a pair of curly braces or something. You won't get useful profiling results out of it but at least it will compile. Separate crates is better than this because when compiling with udeps this will pull in all the profilers and CI time will suffer.

Yet another improvement would be to generate a meaningful compilation error when several features are enabled: pull request that added dependency on profiling crate also removed udeps from CI explaining it as cargo udeps fails to compile the "profiling-procmacros" crate for some reason. No idea why this is; disabling t-udeps for now.

Closing as this has been open for a long time with no movement. I'm not aware of this causing real problems for people using this crate as it's intended (turned on for temporary local development only.)