Hacker News new | past | comments | ask | show | jobs | submit | notanaverageman's comments login

The hardest thing for me when I started using Go after a decade of writing C# is to accept that Go and C# are very different and Go is a much simpler language. It is actually more similar to C than C#.

For a time I tried to write Go like it is C# and got frustrated a lot. After accepting that they are fundamentally different languages it became much easier.


For a large group of people, lifespan of a phone is the same as the lifespan of the battery. They complain that the phone gets slower day by day, but they don’t know what causes it. Most of them come up with deleting WhatsApp messages so that the storage will be freed and phone will get faster.

Showing a persistent notification that “the battery has degraded and should be replaced” can increase the average lifespan of a smart phone significantly. These people don’t really care about shiny new apps or security patches. They just call people and send messages on WhatsApp. And maybe do some browsing on Facebook.

On iPhones, if the battery is degraded at least it drains up quickly and this hints that there is a problem with the battery. However, on most Android phones even 4-5 years old batteries last at least a day and they do so by reducing the CPU clock speed significantly. I know that Apple got fined for doing this in the past, but I haven’t heard any Android brand got fined for the same thing.

As anecdata, I have replaced the battery of my iPhone 6S at least three times and I will probably replace it again in a few months. And the phone is still very much usable.


Reduced speed with degraded battery doesn't only happen for phones unfortunately. My Lenovo laptop is painfully slow when unplugged. I thought something is broken, but Lenovo told me it's because the battery is degraded. The consequences are similar as with phones: The battery can't be easily changed and the costs for letting it be changed by Lenovo are not worth it considering the age of the laptop. So I'll likely live with it until I'm annoyed enough to buy a new one.


Also with some gaming laptops just cant provide the power output from the battery so needs to be plugged in for full performance.



More than 50000 people died there in one of the fiercest fights of WWI and many of those people was buried there without a grave. So those lands are treated as graveyards of martyrs, and therefore have historical and cultural importance.

Turkish people would not accept building the bridge and the roads there even if it was cheaper.


You mean the Martyrs' Memorial in Çardak? I guess. It still has a big highway going through the town (which is what this bridge connects to regardless), and I would think a suspension bridge would look very nice and respectful in the background of this view:

https://en.wikipedia.org/wiki/%C3%87anakkale_Martyrs%27_Memo...


You still have to use stackalloc to allocate on stack. With Span<T> you don’t have to use the unsafe keyword and you can pass the allocated array to other functions easily.


Note that most of the performance improvements come from PGO, which is enabled with following environment variables. PGO is not enabled in .NET 6 by default, but will be in .NET 7 IIRC.

  set DOTNET_ReadyToRun=0 
  set DOTNET_TieredPGO=1 
  set DOTNET_TC_QuickJitForLoops=1
Here are my own benchmarks from a CPU intensive application without any IO and already optimized for allocations. Application runs a task graph either serially or in parallel.

  .NET 5
  --------------------------
  |      Method |     Mean |
  |------------ |---------:|
  | RunParallel | 473.4 us |
  |         Run | 513.5 us |

  .NET 6
  --------------------------
  |      Method |     Mean |
  |------------ |---------:|
  | RunParallel | 452.5 us |
  |         Run | 499.8 us |

  .NET 6 PGO
  --------------------------
  |      Method |     Mean |
  |------------ |---------:|
  | RunParallel | 381.8 us |
  |         Run | 412.2 us |

  .NET 5 - .NET 6     -> ~5%
  .NET 5 - .NET 6 PGO -> ~20%
Here is what I learned from micro-optimizing a .NET application:

- Use BenchmarkDotNet[0] for general measurements and Visual Studio profiler tools for detailed inspection. They help a lot.

- Memory allocations matter. Using capturing lambdas, LINQ, even foreach on interfaces introduce allocations and slows down the application. You can use ClrHeapAllocationAnalyzer[1] to find these hidden allocations.

- Using abstractions with interfaces and casting back to concrete types cause some overhead, though PGO will probably eliminate most of these.

- Use LINQ cautiously as its variants are mostly slower than explicit coding. E.g. .Any() vs .Count == 0

- Checking Logger.IsEnabled() before calling Logger.Debug() etc. helps a lot. You can even automate this with Fody [2], but it breaks Edit&Continue and possibly .NET Hot Reload too, so it may hinder your productivity.

[0] https://github.com/dotnet/BenchmarkDotNet

[1] https://github.com/microsoft/RoslynClrHeapAllocationAnalyzer

[2] https://github.com/jorisdebock/LoggerIsEnabled.Fody


> - Use LINQ cautiously as its variants are mostly slower than explicit coding. E.g. .Any() vs .Count == 0

Is this really true for the example? To me it seems that the implementation for .Any actually uses .Count when available, see https://github.com/dotnet/runtime/blob/main/src/libraries/Sy...


Any method does an extra null check and a cast to ICollection<T> which incur unnecessary performance degradation. Of course this is in micro optimization scale. If you do not call Any() on a hot path it does not matter which one you use.


> - Use LINQ cautiously as its variants are mostly slower than explicit coding. E.g. .Any() vs .Count == 0

When using LINQ also be aware that .First(predicate) is significantly slower than .Where(predicate).First() when called on List<T> and T[]. This is true for essentially all methods like Last, Single, Count etc. Don't trust Visual Studio when it's telling you to "optimize" this.

But if you want the last bit of performance, you shouldn't use LINQ anyways.


Do you know why that is? That's very interesting.


Not sure if it is still the case, but it used to be that First did a fairly naive foreach over the IEnumerable while Where has several collection specific type checks that allow it to use MoveNext and maybe other more efficient ways to traverse the collection.


LINQ is parsing a tree of System.Linq.Expression here and the cases of First(pred) etc. are just not optimized because of the added complexity with little benefit. It only recently became a problem when Visual Studio got a new built-in analyzer that tells people to "optimize" this.


If you're using LINQ on a list, it will not use Expressions, but a plain Func. So nothing will get parsed either way.

The difference, as @sbelskie already mentioned, is that Where has an optimization for List, while First only uses the naive enumerator.


As for BenchmarkDotNet, I totally agree with you in general - it's the best option available for micro-benchmarks. But if you want to run a benchmark involving a fairly complex interaction, multithreading, etc. (caching benchmark that I used is of this kind - it runs on client + server process, uses SQL Server hosted in Docker, etc.), it's rarely the best fit.

On a positive side, I can assure you I know how to run such benchmarks properly - i.e. things like warmup, explicit GC before / after are just some of the aspects taken into account. If you're curious about some other benchmarks I ran in past, check out https://itnext.io/geting-4x-speedup-with-net-core-3-0-simd-i... and https://github.com/alexyakunin/GCBurn


I still just use System.Diagnostics for debug statements, any left overs are no problems in production code, they don't even get compiled.

I'm interested, what's the advantage for you to using ILogger instead?


I use it for structured logging, which makes filtering and searching very convenient. E.g. I can filter by an object’s id and a property to see which tasks change the property of that specific object and in what order. Serilog[0] and Seq[1] are the best tools for this in my opinion.

[0] https://github.com/serilog/serilog

[1] https://datalust.co/seq


Can log to different outputs, such as a remote sink or a file.


Hi there, the author of the original post is here. PGO is disabled in .NET 6 by default mainly because of trade-offs associated w/ the startup time - and IMO it's totally reasonable assuming .NET 6 brings decent speed benefits even w/o PGO.

I turned it on mostly to show what you can expect from a service that runs for a while (more than a few minutes?) in a typical server-side scenario after migration to .NET 6 - IMO it's totally reasonable to turn PGO on for nearly any service of this kind.


FYI your chart is very unreadable on mobile.


Thanks, I removed unnecessary parts. It should be better now.


A lot better now, thanks.


WPF is still Windows only. It will not work on a Linux machine.


Indees it seems to be a dead end.

https://github.com/dotnet/wpf/issues/48

Thanks for clarifying.


For a WPF-like development experience that's also cross-platform, perhaps take a look at Avalonia: http://avaloniaui.net/. It's not a drop-in replacement, but very, very similar.


Each generation has its own problems. Today's problems may seem scary to us, but world has seen worse days.

From Billy Joel:

  We didn't start the fire
  It was always burning
  Since the world's been turning
  We didn't start the fire
  But when we are gone
  It will still burn on and on and on and on


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: