Live data from Hacker News

What .NET 10 GC changes mean for developers

roxeem.com

241–250 of 253 posts

Re: What .NET 10 GC changes mean for developers

#241
post #7

Earlier quoted context omitted.

One limitation of the stack is that it needs to be contiguous virtual addresses, so it was often limited when devices just didn't have the virtual address space to "waste" on a large stack for every thread in a process. But 64 bits of virtual address space is large enough that you can keep the stacks far enough apart that even for pretty extreme numbers of threads you'll run out of physical memory before they start c…

> So you can always just allocate more physical pages to the stack as needed, similar to the heap. You set the (max) stack size once when you create the thread and you can’t increase the (max) size after that. Processes see a virtual address space that is handled by the OS, so you would have to involve the OS if you needed to add to the stack size dynamically.

After process start and it's initial state, the stack is just another virtual address and the just sp another register. It can be mapped, remapped, changed to point to whatever. With overcommit even the initial state may not be entirely backed by physical pages.

Many userspace apps already do custom stack handling, it's how things like green threads work. And many non-native runtimes like .net already have custom handling for their managed stacks, as they often have different requirements and limitations to the "native" stack, and often incompatible formats and trying to isolate from possible bugs means there's less benefit to sharing the same stack with "native" code.

Re: What .NET 10 GC changes mean for developers

#242

Earlier quoted context omitted.

No, it is not. Referential transparency Plus F# as a functional language has significant gaps that prevent effective refactoring, such as lack of support for named arguments to curried functions.

Can you give me an example where lack of support for named arguments to curried functions makes refactoring difficult? I'm having trouble understanding how that would happen.

For one there's no way to add a curried parameter without doThing4-style naming and lack of named arguments implies you can't have a default value for the new parameter.

Another one is if you want to add a curried parameter to the end of the parameter list, and you have code like

  |> myFunc a b
  |> ...
You can't just say

  |> myFunc a b z=10
  |> ...

instead, you have to rewrite the whole pipe.

Re: What .NET 10 GC changes mean for developers

#243

Earlier quoted context omitted.

Can you give me an example where lack of support for named arguments to curried functions makes refactoring difficult? I'm having trouble understanding how that would happen.

For one there's no way to add a curried parameter without doThing4-style naming and lack of named arguments implies you can't have a default value for the new parameter. Another one is if you want to add a curried parameter to the end of the parameter list, and you have code like |> myFunc a b |> ... You can't just say |> myFunc a b z=10 |> ... instead, you have to rewrite the whole pipe.

OK, I think I see what you mean. I certainly agree that named arguments with default values can be useful, but are not supported by curried functions.

Re: What .NET 10 GC changes mean for developers

#244
post #241

Earlier quoted context omitted.

> So you can always just allocate more physical pages to the stack as needed, similar to the heap. You set the (max) stack size once when you create the thread and you can’t increase the (max) size after that. Processes see a virtual address space that is handled by the OS, so you would have to involve the OS if you needed to add to the stack size dynamically.

After process start and it's initial state, the stack is just another virtual address and the just sp another register. It can be mapped, remapped, changed to point to whatever. With overcommit even the initial state may not be entirely backed by physical pages. Many userspace apps already do custom stack handling, it's how things like green threads work. And many non-native runtimes like .net already have custom han…

[dead]

Re: What .NET 10 GC changes mean for developers

#245
Garbage collection improvements are always welcome. We've had some .NET services where GC pauses were causing noticeable latency spikes under load.

I think the regional GC approach is potentially promising if it’s for applications with large heaps. I’ll bet most web apps probably won't notice much difference though.

Re: What .NET 10 GC changes mean for developers

#246
post #223

Earlier quoted context omitted.

Attributes do nothing at all on their own. It's someone else's code that does magic by reflecting on your types and looking for those attributes. That may seem like a trivial distinction, but there's a big difference between "the language is doing magic" and "some poorly documented library I'm using is doing magic". I rarely use and generally dislike attributes. I sometimes wonder if C# would be better off without th…

> But I haven't used source generators in C# in at least 10 years, and I honestly don't know why anyone would at this point. A challenge with .NET web APIs is that it's not possible to detect when interacting with a payload deserialized from JSON whether it's `null` because it was set to `null` or `null` because it was not supplied. A common way to work around this is to provide a `IsSet` boolean: private bool _isNam…

That is tedious with or without a source generator, mainly because there's a much better way to do it:

    public Optional Name;
With Optional being something like:

    class Optional {
      public T? Value;
      public bool IsSet;
    }
I'm actually partial to using IEnumerable for this, and I'd reverse the boolean:

    class Optional {
      public IEnumerable ValueOrEmpty;
      public bool IsExplicitNull;
    }
With this approach (either one) you can easily define Map (or "Select", if you choose LINQ verbiage) on Optional and go delete 80% of your "if" statements that are checking that boolean.

Why mess with source generators? They're just making it slightly easier to do this in a way that is really painful.

I'd strongly recommend that if you find yourself wanting Null to represent two different ideas, then you actually just want those two different ideas represented explicitly, e.g. with an Enum. Which you can still do with a basic wrapper like this. The user didn't say "Null", they said "Unknown" or "Not Applicable" or something. Record that.

    public OneOf Name
A good OneOf implementation is here (I have nothing to do with this library, I just like it):

https://github.com/mcintyre321/OneOf

I wrote a JsonConverter for OneOf and just pass those over the wire.

Re: What .NET 10 GC changes mean for developers

#247
post #223

Earlier quoted context omitted.

Attributes do nothing at all on their own. It's someone else's code that does magic by reflecting on your types and looking for those attributes. That may seem like a trivial distinction, but there's a big difference between "the language is doing magic" and "some poorly documented library I'm using is doing magic". I rarely use and generally dislike attributes. I sometimes wonder if C# would be better off without th…

> But I haven't used source generators in C# in at least 10 years Source generators didn't exist in C# 10 years ago. You probably had something else in mind?

Huh? 10 years ago was 2015. Entity Framework had been around for nearly 7 years by then, and as far back as I remember using it, it used source generators to subclass your domain models. Even with "Code First", it generated subclasses for automatic property tracking. The generated files had a whole other extension, like .g.cs or something (it's been a while), and Visual Studio regenerated them on build. I eventually figured out how to use it effectively without any of the silly code generation magic, but it took effort to get it to not generate code.

ASP.NET MVC came with T4 templates for scaffolding out the controllers and views, which I also came to view as an anti-pattern. This stuff was in the official Microsoft tutorials. I'm really not sure why you think these weren't around?

Re: What .NET 10 GC changes mean for developers

#248
post #202
post #200

Earlier quoted context omitted.

I have been coding in C# for 16 years and I have no idea what you mean by "hidden indirection and runtime magic". Maybe it's just invisible to me at this point, but GC is literally the only "invisible magic" I can think of that's core to the language. And I agree that college-level OOP principles are an anti-pattern; stop doing them. C# does not force you to do that at all, except very lightly in some frameworks wher…

Hidden indirection & runtime magic almost always refer to DI frameworks. Reflection is what makes DI feel like "magic". Type signatures don't mean much in reflection-heavy codes. Newcomers won't know many DI framework implicit behaviors & conventions until either they shoot themself in their foot or get RTFM'd. My pet theory is this kind of "magic" is what makes some people like Golang, which favors explicit wiring o…

"Just don't write bad code" means that you can easily avoid some of the anti-patterns that people list as weaknesses of C#. Yes, maybe you inherit code where people do those things, but how much of that is because of C#, and how much is due to it being popular? Any popular language is going to have bucketloads of bad code written in it. Alternatively: "you can write bad code in any language". I'm far more interested in languages that help you write great code than those that prevent you from writing bad code. (Note that I view static typing in the "help you write great code" category -- I am distinguishing "bad code" from "incorrect code" here.)

Yes, some programming languages have more landmines and footguns than others (looking at you, JS), and language designers should strive to avoid those as much as possible. But I actually think that C# does avoid those. That is: most of what people complain about are language features that are genuinely important and useful in a narrow scope, but are abused / applied too broadly. It would be impossible to design a language that knows whether you're using Reflection appropriately or not; the question is whether their inclusion of Reflection at all improves the language (it does). C# chose to be a general-purpose, multi-paradigmatic language, and I think they met that goal with flying colors.

> Newcomers won't know many DI framework implicit behaviors & conventions until either they shoot themself in their foot or get RTFM'd

The question is: does the DI framework reduce the overall complexity or not? Good DI frameworks are built on a very small number of (yes, "magic") conventions that are easy to learn. That being said, bad DI frameworks abound.

And can you imagine any other industry where having to read a few pages of documentation before you understood how to do engineering was looked upon with such derision? WTF is wrong with newcomers having to read a few pages of documentation!?

Re: What .NET 10 GC changes mean for developers

#249
post #247

Earlier quoted context omitted.

> But I haven't used source generators in C# in at least 10 years Source generators didn't exist in C# 10 years ago. You probably had something else in mind?

Huh? 10 years ago was 2015. Entity Framework had been around for nearly 7 years by then, and as far back as I remember using it, it used source generators to subclass your domain models. Even with "Code First", it generated subclasses for automatic property tracking. The generated files had a whole other extension, like .g.cs or something (it's been a while), and Visual Studio regenerated them on build. I eventually…

That's lowercase "source generators". They're referring to title-case "C# Source Generators", an actual feature slowly replacing some uses of reflection.

https://devblogs.microsoft.com/dotnet/introducing-c-source-g...

Re: What .NET 10 GC changes mean for developers

#250

Earlier quoted context omitted.

It's so weird to describe F# as "Python with Types." First of all, Python is Python with Types. And C# is much more similar to Python than F# is.

It all depends on the lens one chooses to view them. None of them are really "functional programming" in the truly modern sense, even F#. As more and more mainstream languages get pattern matching and algebraic data types (such as Python), feature lambdas and immutable values, then these languages converge. However, you don't really get the promises of functional programming such as guaranteed correct composition and…

I am an avid functional programmer (it’s my default when working on solo projects) and I teach a PL class that covers the lambda calculus, LISP, etc. But the bulk of the course uses F#. I’ve been using F# regularly for the last 13 years.

It’s pretty easy to stick to pure F# if what you want is the pure functional programming experience. But what I like about it is its pragmatism, and this is a big reason why it’s the language I chose for the course. It is by-value, eagerly evaluated by default, and has an easy-to-learn idiomatic syntax. It has a large and well-behaved standard library, and you can use C#’s excellent standard library if you need additional things (e.g., mutable data structures). I have used F# in many performance-sensitive applications, and the fact that I can say “you know, inside this function, I’m going to use mutability, raw pointers, and iteration” has been a lifesaver in some places. But because it is a functional language, I can also abstract all that away and pretend that it is functional.

I understand why other FP folks dislike this approach. But the insistence on purity makes many problems artificially difficult. Debugging a lazily evaluated program is a nightmare. There are lots of times I want a well-behaved language but I am not willing to do CS research just to solve common algorithmic problems. The generally pragmatic streak from the SML family makes them easy to love.

Post reply on HN