
DotNetAnywhere: An Alternative .NET Runtime - matthewwarren
http://www.mattwarren.org/2017/10/19/DotNetAnywhere-an-Alternative-.NET-Runtime/
======
chrisb
I'm the original author of DotNetAnywhere.

For all its flaws (and there are quite a few) it was a very interesting
learning exercise, and it worked better than I ever really expected ;)

I don't really intend to ever do any more work on it, especially now that
there are open source "real" implementations. But it's been nice to see it
used in Blazor :)

If you have any questions about it, please ask.

~~~
matthewwarren
Firstly, thanks for writing it!

Here's my questions (assuming you can remember from 6+ years ago):

1) What was the hardest part of .NET to understand and/or implement?

2) Were there any surprising things about the .NET runtime/specification that
you learnt about along the way?

3) Should JIT.c really be called Interpreter.c :-)

~~~
chrisb
My memory is a little vague...

But I'm fairly sure the hardest part to implement was the support for generic
types/methods. It made all the code that handles types way more complex (as
expected I suppose!), and there's definitely a bug or two remaining. Correctly
handling open/closed generic types and construction of types from generic
arguments was painful. It didn't help that I initially implemented only non-
generic type support, then had to hack generics into it. Were I to start again
I'd implement the whole thing in a generic-first way.

The design of classes/structs and they they interact with generics is nice.
And the `constained` IL prefix is a really neat optimization to avoid boxing.
The use of type-agnostic CIL instructions (e.g. `add` can work on int, float,
...) is also a nice touch.

JIT literally stands for "Just In Time". It doesn't say what it's actually
doing just-in-time ;) So (in my opinion) JIT.c is correct. It's translating
CIL opcodes to dna-internal opcodes, which it does just-in-time just before a
method is executed for the first time. The reason it does this at all is
because there are many things to resolve when working from CIL that it's much
better to do just once rather than every time a method is executed. A simple
example is method references, which are by name in CIL, but are a simple
pointer in dna-internal opcodes.

~~~
matthewwarren
Thanks so much for your replies, very informative.

r.e. 'JIT v Interpreted', I should've checked wikipedia, it backs up what
you're saying:

> Most often this consists of translation to machine code, which is then
> executed directly, but can also refer to translation to another format

From [https://en.wikipedia.org/wiki/Just-in-
time_compilation](https://en.wikipedia.org/wiki/Just-in-time_compilation)

------
j_s
There are a couple partial .NET runtimes reimplemented in JavaScript rather
than compiled to WebAssembly; they are usually tied in with C# -> JavaScript
generators.

[https://github.com/nikhilk/scriptsharp](https://github.com/nikhilk/scriptsharp)
was kind of the granddaddy of them all, with no updates since 2013.

[https://github.com/bridgedotnet/Bridge](https://github.com/bridgedotnet/Bridge)
Saltarelle was acquired by Bridge.NET mid-2015:
[https://blog.bridge.net/bridge-net-acquires-
saltarelle-c77a9...](https://blog.bridge.net/bridge-net-acquires-
saltarelle-c77a9633e384) and seems to be going strong.

[https://github.com/SharpKit/SharpKit](https://github.com/SharpKit/SharpKit)
went the other way and is now open source, but original L/GPL/references to
licensing for commercial use may have limited growth; it is now MIT.

[http://jsil.org/](http://jsil.org/) mostly demonstrates games, and focuses on
translating MSIL bytecode rather than any specific language or runtime.

~~~
chrisb
I wrote an CIL-to-JS translator too:

[https://github.com/chrisdunelm/DotNetWebToolkit](https://github.com/chrisdunelm/DotNetWebToolkit)

It's not complete, certainly not usable for anything remotely real, but could
handle quite a bit of C#. And was fun to work on :)

------
le-mark
_What I find most impressive about the DotNetAnywhere runtime is that it was
developed by one person and is less that 40,000 lines of code!!_

Nice write up, thanks. I wasn't aware of this project, it is very impressive.
Does anyone know of similar projects for .net or Java?

~~~
Sir_Cmpwn
There's IKVM, which is a managed JVM written in C# and is also capable of
converting Java bytecode to CLR bytecode.

[http://www.ikvm.net/](http://www.ikvm.net/)

~~~
j_s
IKVM is feature-complete enough to remain useful for quite some time (with the
full .NET framework), but keep this in mind:

The End of IKVM.NET |
[https://news.ycombinator.com/item?id=14174774](https://news.ycombinator.com/item?id=14174774)
(Apr 2017, 108 comments)

------
ziotom78
Had I read an article opening with the sentence: «Here is a .NET runtime
alternative which is however 100 times slower…», I would have quickly
dismissed it, shame on me. This article is right, the DotNetAnywhere code
really seems a gem, well worth to study!

~~~
matthewwarren
> Had I read an article opening with the sentence: «Here is a .NET runtime
> alternative which is however 100 times slower…», I would have quickly
> dismissed it

I deliberately didn't start with Benchmarks, pretty much for that reason! Plus
I put a huge caveat in before I showed the results.

> This article is right, the DotNetAnywhere code really seems a gem, well
> worth to study!

Glad you think so as well, that's exactly the reason that I wrote about it.
It's relatively unknown and if nothing else it's a really useful resource
(whether it's suitable for production is another matter)

------
singularity2001
run .Net in your browser via DotNetAnywhere in wasm:
[https://github.com/aspnet/blazor-hackathon](https://github.com/aspnet/blazor-
hackathon) (interpreted)
[https://www.youtube.com/watch?v=MiLAE6HMr10](https://www.youtube.com/watch?v=MiLAE6HMr10)

~~~
nwah1
Great suggestion, this is probably the killer app for this. I heard that the
Mono and .NET teams are working on a new linker that should also help bring
down the bloat, and help make .NET via WebAssembly less ridiculous in terms of
overhead.

I have no idea if it would be compatible with DotNetAnywhere

[https://github.com/dotnet/announcements/issues/30](https://github.com/dotnet/announcements/issues/30)

------
typetehcodez
The memory issues with DNA are frighting. If Chrome didn't hog enough of your
ram before... it will NOW! Bwahahahahaha!

~~~
matthewwarren
> The memory issues with DNA are frighting.

Which memory issues do you mean? The items that are covered in this section
[http://mattwarren.org/2017/10/19/DotNetAnywhere-an-
Alternati...](http://mattwarren.org/2017/10/19/DotNetAnywhere-an-
Alternative-.NET-Runtime/#garbage-collector) ('Garbage Collector') or
something else?

~~~
typetehcodez
Yeah, trusting the GC - reading the original author's comments on it:

> Mind you, the whole heap code really needs a rewrite to reduce per-object
> memory overhead, and to remove the need for the binary tree of allocations.
> Not really thinking of a generational GC, that would probably add to much
> code. This was something I vaguely intended to do, but never got around to.
> The current heap code was just the simplest thing to get GC working quickly.
> The very initial implementation did no GC at all. It was beautifully fast,
> but ran out of memory rather too quickly.

~~~
matthewwarren
Yeah, the GC code is certainly not optimal (in terms of memory usage), but I
don't know if that means you can't trust it.

At least in the simple tests I did it behaved as expected, but I know that
testing a GC for correctness is not a simple task!!

~~~
typetehcodez
>What I find most impressive about the DotNetAnywhere runtime is that it was
developed by one person and is less that 40,000 lines of code!! For a
comparison the .NET framework Garbage Collector is almost 37,000 lines.

Keeping the code base small is a double edged sword. The trouble with
everything going web-based these days is that script kiddies (myself included)
should have some awareness of how memory is being managed and when to worry
about holding IEnumerables in memory. Your write-up here is interesting and
it's the first I've heard of Blazor. This is all very fascinating you have me
reading the codebase now.

