Live data from Hacker News

Allocation is cheap in .NET until it is not

tooslowexception.com

61–67 of 67 posts

Re: Allocation is cheap in .NET until it is not

#61
post #57

Earlier quoted context omitted.

> of which there's a limit (65k in Android!) Oh man JNI and Android. I've never heard a developer curse up a storm like I did when one of my co-workers inadvertently stumbled across the 512 LocalRef limit(also a fun one) during an intermittent crash repro. By the time he got done with his rant we had to talk him out of purchasing a one-way plane ticket to Mountain View.

As Java dev, there are so many things that just feel wrong on Android. Leaving aside the fact how Google treated Sun, the whole framework has a feeling that was written by former C and C++ devs, learning Java on the job while implementing Android.

Sorry, but if you have constrained plattforms- all the frameworks/software tends to look this way. This is how many gamecodes look internal- and do horrible things behind the scene to keep it save.

So if a native java dev had written the whole plattform, how would he handle the limitations of the plattform any diffrently, except for alot of abstract wrapping and exceptional execptions?

There is a reason why there is no rte every time something comes to the limits of machine feasible. Projecting ones unwillingness to cope with reality on a developer with a difficult job - is sort(off, sad);

Re: Allocation is cheap in .NET until it is not

#62
post #55
post #53

Earlier quoted context omitted.

Can you please point to any resources that talk about heavy optimization options in c#. That 50-fold increase you talk about is very interesting. I would like to learn more.

Here is a list, not easy to track all of them down, but maybe as keywords to easy googling. - structs - unsafe code - stack allocation in unsafe code (think alloca()) - attribute annotations for packing and inline calls across assemblies - ref parameters - ref returns - readonly ref parameters - Span and Memory - Native memory allocation via MarshalInterop, SafeHandles - Buffer and ArraySegment - SIMD (with RyuJIT) -…

Thanks!

Re: Allocation is cheap in .NET until it is not

#63
post #55
post #53

Earlier quoted context omitted.

Can you please point to any resources that talk about heavy optimization options in c#. That 50-fold increase you talk about is very interesting. I would like to learn more.

Here is a list, not easy to track all of them down, but maybe as keywords to easy googling. - structs - unsafe code - stack allocation in unsafe code (think alloca()) - attribute annotations for packing and inline calls across assemblies - ref parameters - ref returns - readonly ref parameters - Span and Memory - Native memory allocation via MarshalInterop, SafeHandles - Buffer and ArraySegment - SIMD (with RyuJIT) -…

Great list. It's important to understand when to use each one of these. Identify your bottleneck, through the use of profilers. Execution time is largely based on memory bus blocking I/O and not the CPU calculations, so if you start with writing SIMD, you're not going to get anywhere.

Accessing data on the stack instead of the heap is the #1 saver of execution time, in my experience. But your bottlenecks might be different. Locally scoped value-type variables are generally on the stack. Object-scoped and static fields and properties are on the heap.

Writes to local variables seem to be faster than reads, IIRC. The fastest operators seem to be the bitwise instructions, IIRC. If running in 32-bit mode, try to work with 32-bit integers. If running in 64-bit mode, try to work with 64-bit integers.

Here's an example of a major, major improvement in performance

for(int x = 0; x {

   for(int y = 0; y 
}

Much faster version (due to storing a copy of Width and Height on the stack instead of the heap):

int width = this.Width;

int height = this.Height;

for(int x = 0; x {

   for(int y = 0; y 
}

My comment here describes roughly the approach I used to take advantage of stack-allocated memory (before Span was available). https://news.ycombinator.com/item?id=15136627

Re: Allocation is cheap in .NET until it is not

#64
post #62
post #55

Earlier quoted context omitted.

Here is a list, not easy to track all of them down, but maybe as keywords to easy googling. - structs - unsafe code - stack allocation in unsafe code (think alloca()) - attribute annotations for packing and inline calls across assemblies - ref parameters - ref returns - readonly ref parameters - Span and Memory - Native memory allocation via MarshalInterop, SafeHandles - Buffer and ArraySegment - SIMD (with RyuJIT) -…

Thanks!

Also be sure to check this out https://gist.github.com/jboner/2841832 Notably the L1/L2 cache vs the main memory reference

Re: Allocation is cheap in .NET until it is not

#65
post #55

Earlier quoted context omitted.

Here is a list, not easy to track all of them down, but maybe as keywords to easy googling. - structs - unsafe code - stack allocation in unsafe code (think alloca()) - attribute annotations for packing and inline calls across assemblies - ref parameters - ref returns - readonly ref parameters - Span and Memory - Native memory allocation via MarshalInterop, SafeHandles - Buffer and ArraySegment - SIMD (with RyuJIT) -…

Great list. It's important to understand when to use each one of these. Identify your bottleneck, through the use of profilers. Execution time is largely based on memory bus blocking I/O and not the CPU calculations, so if you start with writing SIMD, you're not going to get anywhere. Accessing data on the stack instead of the heap is the #1 saver of execution time, in my experience. But your bottlenecks might be dif…

Thanks! Your example is pretty interesting. Any reason why this is the case? In both cases, it is just accessing a memory location to read the value. Are there compiler optimization heuristics at play here? E.g., for the local variable compiler knows that its value is not changing during the loop execution, so it can be pushed to register for faster access.

Re: Allocation is cheap in .NET until it is not

#66
post #65

Earlier quoted context omitted.

Great list. It's important to understand when to use each one of these. Identify your bottleneck, through the use of profilers. Execution time is largely based on memory bus blocking I/O and not the CPU calculations, so if you start with writing SIMD, you're not going to get anywhere. Accessing data on the stack instead of the heap is the #1 saver of execution time, in my experience. But your bottlenecks might be dif…

Thanks! Your example is pretty interesting. Any reason why this is the case? In both cases, it is just accessing a memory location to read the value. Are there compiler optimization heuristics at play here? E.g., for the local variable compiler knows that its value is not changing during the loop execution, so it can be pushed to register for faster access.

Register access isn't the issue. In the first example, this.Width and this.Height are accessing the Width and Height property of the current object. This requires a heap fetch on each iteration of the loop. There may be OS-specific nuances with automatic caching that I can't remember clearly enough to reliably mention.

If you can get rid of all heap lookups in your iterative loop, then you'll see a large speed boost if that was the bottleneck. Local variables exist on the stack, which tends to exist in the CPU cache when the current thread is active. https://msdn.microsoft.com/en-us/library/windows/desktop/ms6...

Unfortunately, method calls in C# have a much higher overhead than in C and C++. If you must do a method call in your loop, be sure to read this to see if your method can be inlined. Only very small methods of 32 IL bytes or less can be inlined: https://stackoverflow.com/questions/473782/inline-functions-...

Re: Allocation is cheap in .NET until it is not

#67
post #57

Earlier quoted context omitted.

As Java dev, there are so many things that just feel wrong on Android. Leaving aside the fact how Google treated Sun, the whole framework has a feeling that was written by former C and C++ devs, learning Java on the job while implementing Android.

Sorry, but if you have constrained plattforms- all the frameworks/software tends to look this way. This is how many gamecodes look internal- and do horrible things behind the scene to keep it save. So if a native java dev had written the whole plattform, how would he handle the limitations of the plattform any diffrently, except for alot of abstract wrapping and exceptional execptions? There is a reason why there is…

That wasn't my point about feeling wrong about Android APIs, surely there are some restrictions due to programming resource constrained devices.

Any Java developer that used Java Card, J2ME or Embedded Java is quite aware of them.

A native Java dev would not have used Hungarian notation, snake case identifiers, allocation of classes just to fake out parameters which could be returned as result,have event handlers with unused parameters repeating AWT design errors and a couple of other things that I could still rant on.

Post reply on HN