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

Use AsParallel() correctly #33769

Open
Tracked by #57797
terrajobst opened this issue Mar 19, 2020 · 14 comments · May be fixed by dotnet/roslyn-analyzers#4126
Open
Tracked by #57797

Use AsParallel() correctly #33769

terrajobst opened this issue Mar 19, 2020 · 14 comments · May be fixed by dotnet/roslyn-analyzers#4126
Assignees
Labels
api-approved API was approved in API review, it can be implemented area-System.Linq.Parallel code-analyzer Marks an issue that suggests a Roslyn analyzer code-fixer Marks an issue that suggests a Roslyn code fixer in-pr There is an active PR which will close this issue when it is merged
Milestone

Comments

@terrajobst
Copy link
Member

terrajobst commented Mar 19, 2020

Using .AsParallel() at the end of a LINQ query, e.g. foreach (var item in src.Select(...).Where(...).AsParallel(...)), is a nop and should either be removed or the AsParallel() moved earlier in the query. I've even seen developers write foreach (var item in src.AsParallel()) thinking it parallelizes the foreach loop, which it doesn't... it'd be good to warn about such misuse.

Category: Performance

@terrajobst terrajobst added api-suggestion Early API idea and discussion, it is NOT ready for implementation area-System.Linq code-analyzer Marks an issue that suggests a Roslyn analyzer labels Mar 19, 2020
@Dotnet-GitSync-Bot Dotnet-GitSync-Bot added the untriaged New issue has not been triaged by the area owner label Mar 19, 2020
@stephentoub
Copy link
Member

Here's an example of the kinds of things we'd like to catch:
dotnet/sdk#10937

@jeffhandley jeffhandley added this to the Future milestone Mar 20, 2020
@jeffhandley jeffhandley added the code-fixer Marks an issue that suggests a Roslyn code fixer label Mar 21, 2020
@jeffhandley
Copy link
Member

Estimates:

  • Analyzer: Medium
  • Fixer: Medium

@terrajobst terrajobst removed the untriaged New issue has not been triaged by the area owner label Mar 21, 2020
@Mrnikbobjeff
Copy link

Mrnikbobjeff commented Aug 30, 2020

Would the fixer simply remove the call? I do not think it can add it earlier in the chain as it may cause race conditions depending on the implementation of the earlier linq chain, e.g. list.Select(x => NonThreadSafeMethod(x)).AsParallel() can only be resolved by removing the code. I guess that is the intended fix? Also, I guess the analyzer only triggers when the AsParallel is directly inside a foreach? Otherwise i may add other methods to the linq call chain after assigning the AsParallel() result at the end of the chain.

@stephentoub
Copy link
Member

stephentoub commented Aug 30, 2020

guess the analyzer only triggers when the AsParallel is directly inside a foreach

Yes

can only be resolved by removing the code. I guess that is the intended fix

That's the safe fix, in that it doesn't change the semantics. It'd be fine to offer multiple fixes, though, with a second option being to move the call to the beginning of the chain, and if the developer chooses that, it's their choice.

@Mrnikbobjeff
Copy link

Mrnikbobjeff commented Aug 30, 2020

I have a working analyzer for the described scenario, as well as the safe fix as you described it. I would still have to integrate it with the analyzer structure in this project but otherwise I would love to work on this if this is available.

@jeffhandley
Copy link
Member

@carlossanlop @buyaa-n Can you follow up with @Mrnikbobjeff on this? We would need to bring this in for API Review if we want to move it forward.

@carlossanlop
Copy link
Member

carlossanlop commented Oct 23, 2020

This comment in dotnet/roslyn-analyzers#2812 gives a clear example of what to detect in a foreach and what should be suggested as a fix.
This issue gives an example of an enumeration that saves the value into a variable.

  • If an AsParallel invocation is found, check if it was added after enumerating invocations like Select or Where.
    • The first case to address should be to detect AsParallel calls inside a foreach.
    • The second case to address should be to detect AsParallel calls anywhere else, like when an enumeration result is saved into a variable.
  • If any of those two cases were found, then the fixer should suggest moving the AsParallel to the first position.

As long as we keep those rules in mind, we think this is ready for review. After it gets approved, we will let @Mrnikbobjeff know so he can start working on it.

Category: Reliability Performance
Analyzer size: Medium
Fixer size: Medium
Suggested severity: Warning
Suggested messages:
- Title: Use 'AsParallel()' correctly
- Message: The 'AsParallel()' method should be called before enumerating.
- Description: The 'AsParallel()' method result is only effective when its returned value is consumed by enumerating methods.

cc @buyaa-n

@carlossanlop carlossanlop modified the milestones: Future, 6.0.0 Oct 23, 2020
@carlossanlop carlossanlop added api-ready-for-review API is ready for review, it is NOT ready for implementation and removed api-suggestion Early API idea and discussion, it is NOT ready for implementation labels Oct 23, 2020
@buyaa-n
Copy link
Contributor

buyaa-n commented Oct 23, 2020

Thank you for your interest in contributing to this analzyer @Mrnikbobjeff, until the proposal get approved please take a look at our definition of done list - the list of tasks/actions need to be completed/taken before, during, and after the analyzer implementation. You do not have to complete all tasks, but your PR needs to cover all requirements related to the analyzer and fixer implementations (first 2 bullets) at least.

@terrajobst terrajobst added api-approved API was approved in API review, it can be implemented and removed api-ready-for-review API is ready for review, it is NOT ready for implementation labels Oct 27, 2020
@terrajobst
Copy link
Member Author

terrajobst commented Oct 27, 2020

Video

This makes sense. The only thing we have to check with Manish is whether they analyzer should report separate IDs due to how fixers are advertised in the IDE.

@Mrnikbobjeff
Copy link

Mrnikbobjeff commented Oct 28, 2020

  • If any of those two cases were found, then the fixer should suggest moving the AsParallel to the first position.

This is surely something which could be done, but I do not think that would be advisable. Suppose I have a Select method which is not threadsafe, then we would introduce bugs with the fixer. This was not mentioned in the Video. I only have the remove fixer implemented as this is always valid.
@carlossanlop

@stephentoub
Copy link
Member

I do not think that would be advisable

If someone added the AsParallel(), they intended for something to be run in parallel. And while we can't know for sure how much of the query that comes before it was intended, as an option I think it's reasonable to offer to fix it with our best guess for where it would go, which is at the beginning. The only 100% safe fix is to remove it, but both can be offered, and if we have any control which is the "default" / first option, it should be the removal.

@Mrnikbobjeff
Copy link

Mrnikbobjeff commented Oct 29, 2020

I do not think that would be advisable

If someone added the AsParallel(), they intended for something to be run in parallel. And while we can't know for sure how much of the query that comes before it was intended, as an option I think it's reasonable to offer to fix it with our best guess for where it would go, which is at the beginning. The only 100% safe fix is to remove it, but both can be offered, and if we have any control which is the "default" / first option, it should be the removal.

I see the reasoning behing not completely removing the AsParallel call, I just was curious as I can not recall a codefix provider which might introduce bugs for fixing compiler warnings. As fas as I know this would be a first for codefix providers. I will still work on adding the second codefix provider

@eiriktsarpalis
Copy link
Member

Hey @Mrnikbobjeff, would you still be interested in picking this up?

@eiriktsarpalis eiriktsarpalis added the in-pr There is an active PR which will close this issue when it is merged label Aug 5, 2021
@buyaa-n buyaa-n modified the milestones: 6.0.0, 7.0.0 Aug 13, 2021
@ghost
Copy link

ghost commented Sep 30, 2021

Tagging subscribers to this area: @tarekgh, @dotnet/area-system-linq-parallel
See info in area-owners.md if you want to be subscribed.

Issue Details

Using .AsParallel() at the end of a LINQ query, e.g. foreach (var item in src.Select(...).Where(...).AsParallel(...)), is a nop and should either be removed or the AsParallel() moved earlier in the query. I've even seen developers write foreach (var item in src.AsParallel()) thinking it parallelizes the foreach loop, which it doesn't... it'd be good to warn about such misuse.

Category: Performance

Author: terrajobst
Assignees: Mrnikbobjeff
Labels:

api-approved, area-System.Linq, area-System.Linq.Parallel, code-analyzer, code-fixer, in pr

Milestone: 7.0.0

@jeffhandley jeffhandley modified the milestones: 7.0.0, Future Jul 9, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api-approved API was approved in API review, it can be implemented area-System.Linq.Parallel code-analyzer Marks an issue that suggests a Roslyn analyzer code-fixer Marks an issue that suggests a Roslyn code fixer in-pr There is an active PR which will close this issue when it is merged
Projects
None yet
Development

Successfully merging a pull request may close this issue.

8 participants