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

Complier should optimize "alloc temporary small object" to "alloc on stack" #2104

Closed
ygc369 opened this issue Apr 20, 2015 · 11 comments
Closed
Labels
Area-External Discussion Feature Request Resolution-External The behavior lies outside the functionality covered by this repository Tenet-Performance Regression in measured performance of the product from goals. Verification Not Required

Comments

@ygc369
Copy link

ygc369 commented Apr 20, 2015

If a small object's reference is never stored in heap or static variables, (only stored in local variables), it is temporary, the complier should alloc it on stack. Thus, GC pressure would be lower.

@sharwell
Copy link
Member

This is a more appropriate request for dotnet/coreclr. The C# and VB compilers have no control over this.

Considering we have the ability to create user-defined value types which are directly supported by the runtime, I'm wondering if this optimization would provide less benefits than similar optimizations applied to the JVM (and if so, to what extent).

@svick
Copy link
Contributor

svick commented Apr 20, 2015

we have the ability to create user-defined value types

I think that means that this optimization could be done by Roslyn, it could generate a struct and a class for each source code class and use the struct version if it can prove it's safe.

Though doing it in the runtime still sounds like a much better option, because the Roslyn-based optimization would probably be quite limited.

@HaloFour
Copy link

I think his comment was more about the fact that the CLR has value types at all whereas the JVM only has its set of primitives. If you needed a complex type on the stack you at least have that option. Having Roslyn automatically generate both seems like overkill with limited benefit.

I suspect that the original request involves any class that already exists. As mentioned, that is simply not possible in the CLR as the only IL opcode to initialize a class handles the allocation for you. Even assuming that the CLR could be modified to support the new variable types and op codes to initialize classes on the stack there are a number of real challenges. For example, you couldn't define the variable of a base type and then instantiate a derived type since they could have different footprints. There's also no practical way of knowing that some method wouldn't want to take that stack reference and slap it into a field somewhere.

@VSadov
Copy link
Member

VSadov commented Apr 20, 2015

Note that

  • if the instance contains reference fields, JIT still needs to be report them to GC as roots if GC happens, but the stack-alloced instance itself should not be reported (since its address is does not point to the heap)
  • Whether this optimization is profitable may be dependent on environment - x86 and x64 may have different thresholds for what is considered "small"
  • We cannot replace class with a struct transparently, that is simply not possible at IL level, not as long as you want to use any members.
  • ...

There are many reasons why it is much more appropriate to do this kind of optimizations at JIT time.

@sharwell
Copy link
Member

@HaloFour The JVM doesn't have opcodes for stack allocation either. Instead, a technique known as escape analysis is used to identify classes which can be allocated on the stack instead of on the heap.

@VSadov VSadov added Enhancement Discussion Resolution-External The behavior lies outside the functionality covered by this repository Tenet-Performance Regression in measured performance of the product from goals. labels Apr 20, 2015
@VSadov VSadov added this to the Unknown milestone Apr 20, 2015
@ygc369
Copy link
Author

ygc369 commented Apr 21, 2015

I think this idea need effort of both roslyn and coreclr teams.
This idea is useful, for example, when we use keyword "params", it means creating an array in heap, but I think this is not necessary, why not use stack?
void example(bool a, params int[] b) { ... };
example(true, 1, 2, 3); //why not use stack to store parameters "1, 2, 3"?

@JesOb
Copy link

JesOb commented Aug 20, 2015

Also most of Linq queries can be allocated on stack.
e.g.

health += _cards.SelectMany( card => card.BoostTemplate.Effects ).OfType<AddHealthEffect>( ).Sum( e => e.Amount );

all this can be converted by Roslyn to stack logic like this:

var amount = 0;
foreach ( var card in _cards )
{
    foreach ( var effect in card.BoostTemplate.Effects )
    {
        if( effect is AddHealthEffect )
        {
            amount += ((AddHealthEffect)effect).Amount;
        }
    }
}

health += amount;

For all this Roslyn need to store data about parameter usage in functions and function purity.
So it will know how each function use each parameter and can know can it allocate something on stack to pass in function or not.

And additionally colorcode all allocations in IDE so we can know we allocate on stack or on GC.

@mattwarren
Copy link

@Jes28 There's an existing tool called LINQ Optimiser that does optimisations similar to this (although I don't know if it'll do the exact optimisation that you outlined)

Either way it would be nicer if it was done automaticially, rather than via a library.

@jmarolf
Copy link
Contributor

jmarolf commented Oct 15, 2015

@VSadov @gafter Should this bug be closed and a new one filed on the CLR team?

@VSadov
Copy link
Member

VSadov commented Oct 15, 2015

Yes. This kind of optimization can only happen at JIT level.

@gafter
Copy link
Member

gafter commented Oct 15, 2015

@ygc369 You are welcome to suggest this in dotnet/coreclr

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-External Discussion Feature Request Resolution-External The behavior lies outside the functionality covered by this repository Tenet-Performance Regression in measured performance of the product from goals. Verification Not Required
Projects
None yet
Development

No branches or pull requests