
Mono's New .NET Interpreter - benaadams
http://www.mono-project.com/news/2017/11/13/mono-interpreter/
======
peoplewindow
It's interesting how .NET is converging on the same runtime techniques used in
Java and yet how drastically far behind they are. The Java guys realised that
an interpreter was still useful decades ago. Tiered compilation shipped in
Java 8, and that was more complex to implement as there were two JITs, so JITd
code still had to do profiling.

It's also quite interesting that the interpreter was dropped due to the
complexity introduced by having generics in the runtime. A long time ago I
thought it was self evident that type erasure was a poor way to do generics,
but Brian Goetz has been arguing persistently for years now that type erasure
isn't necessarily a bug, just a different tradeoff. With runtime complexity
being one of the factors that weighed into the decision ... something that's
easier to understand now I read this blog post.

There are some things I like about .NET though it was a long time since I did
any, but HotSpot seems so dramatically far ahead and the distance is
increasing. The major selling point of .NET over Java originally was supposed
to be great multi-language support (well, and better Windows support), but
there are way more languages targeting the JVM than the CLR these days.
HotSpot does tiered compilation, it now does AOT compilation too, it has a new
JIT called Graal that either matches or completely smokes the best available
runtimes for almost every language, and IntelliJ is every bit the match for
Visual Studio. And it's all cross platform.

So what's .NET's major selling point these days?

~~~
Const-me
Excellent GUI frameworks on most platforms.

Much better unmanaged interop story: [DllImport] (btw it works on all
platforms, e.g. on Linux it imports from .so libraries), structures, unsigned
integers.

Better multithreading: thread pool, synchronization contexts, async-await.

Unsafe code, pointer arithmetic.

LINQ

~~~
pjmlp
Yeah, Mark Reinhold already stated multiple times that JNI was designed on
purpose to be hard, because Sun wanted to drive people away from writing
unmanaged code.

Thanks to JRuby guys and Project Panama, Java will eventually get a .NET like
interop story, but it is still in the future. :(

~~~
peoplewindow
Wow when did he say that?

~~~
pjmlp
At the JavaOne 2013 Technical Keynote.

[https://blogs.oracle.com/java/the-javaone-2013-technical-
key...](https://blogs.oracle.com/java/the-javaone-2013-technical-keynote)

<quote> He mentioned JNI 2.0 and said, “It just shouldn’t be so hard to
integrate Java with native code after all these years.” </quote>

For the full context, you need to watch the keynote.

------
gmaster1440
Curious to see how this plays out with Microsoft investing in cross-platform
development with .NET Core and .NET Standard.

The consequences of having multiple competing cross-platform options are
already evident when using tools like intellisense in VS Code where you can
(or used to be able to) switch between Mono and .NET Core runtimes and certain
libraries were only compatible with one. And then there are build tools like
Paket which currently only support Mono even though Paket itself can provision
.NET Core runtimes.

~~~
iainmerrick
_.NET Core and .NET Standard_

I don't understand why they need so many different "cross-platform" standards.
Why is the platform so fragmented when MS controls the whole thing?

~~~
hitgeek
.Net Standard is the standard. There is only 1 standard.

.Net Core is one implementation of the standard. .Net 4.6 is another
implementation of the standard. Mono, Xamarin, Universal Windows Platforms are
other implementations.

The idea is that any code written for .Net standard, will work across the
different implementations.

~~~
iainmerrick
As I said, I don't really understand how it's all supposed to fit together,
but what I've found in practice is that completely random and innocuous
methods are missing from the System frameworks depending on which "standard"
you target in Visual Studio.

~~~
akoeplinger
The .NET Standard spec has multiple _versions_, each of them adding more APIs:
[https://github.com/dotnet/standard/blob/master/docs/versions...](https://github.com/dotnet/standard/blob/master/docs/versions.md)

It's true that .NET Standard 1.0-1.6 had a lot of gaps but these should be
rectified with 2.0 now so you shouldn't run into these problems anymore
(otherwise there's usually a good reason why a method/API is missing from the
standard).

Disclaimer: I'm working on Mono for Microsoft/Xamarin, primarily class
libraries and tools.

~~~
oaiey
Thanks for your work!

------
yodon
It’s just mentioned as an aside in this article, but the work the Mono team is
doing on WebAssembly is super exciting. Can’t wait to start messing with it.

~~~
lewurm
check out
[https://twitter.com/kumpera/status/924007954696646656](https://twitter.com/kumpera/status/924007954696646656)
and [http://blog.stevensanderson.com/2017/11/05/blazor-on-
mono/](http://blog.stevensanderson.com/2017/11/05/blazor-on-mono/)

~~~
yodon
And WebAssembly support merged into Mono master branch last week
[https://github.com/mono/mono/pull/5924](https://github.com/mono/mono/pull/5924)
(not available as a release build, but soon)

------
Annatar
_For example, some game developers like to adjust and tweak their game code,
without having to trigger a full recompilation. The static compilation makes
this scenario impractical, so they resort to embedding a scripting language
into their game code to quickly iterate and tune their projects._

There is a programming language where every new expression causes incremental
compilation and linking inherently, natively: it’s called Lisp.

------
alkonaut
What is the main attraction of a proper interpreter vs. the with the compiler
built into the platform (so static, but at runtime) that we have with Roslyn?
I do some in-app scripting etc and I basically just compile/run code at
runtime using Roslyn then. Performance is probably a benefit of doing that,
but what is the drawback? is it more overhead e.g. in an interactive setting
it might not be responsive for a REPL?

~~~
chrisseaton
Roslyn is entirely unrelated. That's the compiler to CLIR. We're talking about
the runtime interpreter and compiler to native code.

~~~
alkonaut
Yes? My question was "whats the benefit of an interpreter for runtime code
exec, over using a compiler-as-a-service like Roslyn"

~~~
chrisseaton
You've asked what is the benefit of using apples over oranges. The two things
are unrelated.

When you use Roslyn you still need either a JIT or an interpreter to execute
the output of Roslyn. You can't ask what is the benefit of using the
interpreter over using Roslyn as you cannot do that. They don't fit into the
same place in the system. They don't do the same job. They aren't
alternatives.

It's a nonsense question.

~~~
alkonaut
This is a somewhat better answer :) The reason I'm asking was because the
interpreter was framed as a solution to in-app code execution (e.g like Lua in
many game engines) - but this type of scripting is exactly what I use Roslyn
for. So if I can rephrase it: what is the benefit of interpreted scripts vs
dynamic compilation of scripts in the context of , for example, app scripting?
Specifically _in .NET apps_. Not e.g. a C++ app (there it's obvious as a
replacement for e.g Lua)

> When you use Roslyn you still need either a JIT or an interpreter

Yes: Assume I'm already _in_ a .NET appxontext so yes I have the JIT
available. Does that make the interpreter less attractive as I can just load
compiled code there?

I'm guessing then the benefit might be less initial overhead, but at the
expense of slower execution?

~~~
chrisseaton
This still doesn't make any sense:

> but this type of scripting is exactly what I use Roslyn for

Because you aren't using Roslyn to execute anything. You're using it to
compile C# to CIL. That CIL is then executed by a different part of the system
- the JIT. It's that entirely unrelated part of the system that is being
talked about being replaced with an optional interpreter instead.

Roslyn goes from C# to CIL.

The JIT and interpreter execute CIL. They don't know or care that it comes
from Roslyn and the fact that you use Roslyn or the command line C# compiler
to generate the CIL is irrelevant.

You're being tripped up by the fact that the system has multiple levels of
compilers. You're thinking about one level but this discussion is about
another level.

But anyway there is actually a helpful answer to this question:

> what is the benefit of interpreted scripts vs dynamic compilation of scripts
> in the context of , for example, app scripting?

The interpreter will probably use less memory and run your code faster first
time. You probably don't care about less memory in a game unless you are
running in a very constrained system, and you probably don't care about first-
time execution as either these scripts run every frame and so it's critical
they're very fast, or they run once a few seconds or so in which case who
cares how fast they run.

~~~
alkonaut
> Because you aren't using Roslyn to execute anything. You're using it to
> compile C# to CIL. That CIL is then executed by a different part of the
> system - the JIT.

Right - with Roslyn Run("somecode") means creating an assembly from the code,
then loading it into the current AppContext and executing it there. If I were
to run an interpreter then Run ("someCode") is interpreted. I get that.

My question was still only: would an application chose one or the other, when
given both options. I get that they are completely separate ideas and Roslyn
doesn't do anything an interpreter does (Roslyn _and_ jit does) - but
"compile+load" and "interpret" both offer a way to solve the Run("somecode")
problem, which is why they are still somewhat related in the specific context
of a .NET app with scripting

~~~
lewurm
Ideally, an application doesn't have to choose, but the runtime uses some good
defaults. For example, let's have a look at the HotSpot JVM: A Java method
first gets executed in the interpreter, then, if it's hot enough it will
compile the method with the C1 JIT, and then later uses the C2 JIT to bring
the method up to full peak performance. There is also some profiling going on
that is fed into the JITs to guide optimizations. The transition between the
execution tiers is based on some heuristics and is kinda complex.

Do you need to care as an application? Ideally no :-) It should be transparent
to the user and it's the runtime's job to do the best available thing for you.
(Sure, the runtime can be tweaked for specific workloads etc.)

In Mono we aren't there yet: the interpreter is _currently_ useful for
restricted targets like iOS, where a JIT can't be used due to security
concerns and AOT comes with certain limitations (that is, loading assemblies
at runtime and execute them). If you want to use Mono's Interpreter to run
roslyn, you can explicitly tell the runtime to do so, but it doesn't make much
sense today, because it will give you less performance than the available JIT;
we don't support switching the execution engine on the fly for single methods
_yet_ (it's also called tiered compilation).

------
FrgmntnFatigue
What is the rationale for keeping working on mono rather than just port its
unique libraries (gtk# etc.) to coreclr ?

