C
C#5d ago
ero

Sharplab Clone Prototype

I wanna create a site like Sharplab in the hopes of possibly creating something more pleasant to use. My goal is to embed the VSCode text editor with the C# grammar (for syntax highlighting) and the Roslyn LSP (for warnings and errors). A major criterion to fulfill is fast loading of the page. I want to offer the ability to choose different versions/branches of Roslyn, the ability to view decompiled C#, IL, and ASM outputs for different runtimes. I'm looking for some opinions on what framework I should go with for my frontend. Since startup time is a concern, should I even go with .NET?
110 Replies
Angius
Angius5d ago
I mean, if you want to embed VS Code in the browser, you'll be using Monaco, not any other specific frontend framework
ero
eroOP5d ago
what exactly is monaco then? i imagined i could use anything to embed the editor?
Angius
Angius5d ago
Monaco is the editor
ero
eroOP5d ago
ah
Angius
Angius5d ago
Unless you want to, dunno, surround that editor window with other stuff I guess you could do that, sure. Any frontend framework should be fine
ero
eroOP5d ago
well yes, i need to offer some controls for the user to choose the options i listed
Angius
Angius5d ago
Most sites that rely on Monaco and include their own stuff rather choose to extend Monaco itself Be it via a plugin, or editing the menu bar, or what have you Check out Codesandbox for example
ero
eroOP5d ago
i'd honestly just make it a vscode extension if i could, but i've always had a really tough time even getting started there which makes me think opening this post might have been kind of a pointless effort i think my idea is too ambitious for what i know about web dev (nothing)
333fred
333fred5d ago
I hate to tell you "don't", but... check out https://lab.razor.fyi Which is really already that
ero
eroOP5d ago
i've seen it, it's really not that
333fred
333fred5d ago
It really is
ero
eroOP5d ago
does not have asm does not have syntax highlighting does not have diagnostics
333fred
333fred5d ago
Has syntax highlighting and diagnostics Does not have asm, true, because that's very hard to do with a wasm running on your box, rather than on a real server somewhere Already uses monaco, even has vim mode Jan has been experimenting with more complete lsp support, not sure what the status on that is
ero
eroOP5d ago
i'm not really sure what i'm missing then, it does not have syntax highlighting for me
333fred
333fred5d ago
No description
ero
eroOP5d ago
and neither does it for you
333fred
333fred5d ago
Uh Yes it does?
ero
eroOP5d ago
it highlights keywords, whoopdiedoo
333fred
333fred5d ago
Ok then. If that's your reaction to "this already exists", you do you I guess
ero
eroOP5d ago
that's exactly why this post exists :p
333fred
333fred5d ago
Consider contributing to the existing project rather than trying to make your own though Because this is a lot of work
ero
eroOP5d ago
No description
ero
eroOP5d ago
No description
ero
eroOP5d ago
i'm so ungrateful
333fred
333fred5d ago
Share a link
ero
eroOP5d ago
MODiX
MODiX5d ago
ero
lab.razor.fyi (click here)
class Program1 {
static void Main() { }
}
class Program1 {
static void Main() { }
}
React with ❌ to remove this embed.
ero
eroOP5d ago
No description
ero
eroOP5d ago
??? genons
333fred
333fred5d ago
You have two files
ero
eroOP5d ago
okay maybe some caching issue well yeah idk you wanted the link
333fred
333fred5d ago
@Jan Jones not sure why this isn't displaying the actual error in the list; it shows it when you go to the second tab Probably compiling as a dll to show the errors, but then compiling as an executable to run? That would also explain why IL and decompiled C# are visible
jjones
jjones5d ago
yes, we are compiling as DLL by default (you can change that in Configuration), but we compile as EXE in Run, I have improved the experience in a branch where I'm currently working on improving intellisense - see https://ls.dotnetinternals.pages.dev/#47Ll4g4oyk8vSsw11EsuFtJLzkksLlaACXFVcykoKCgUlySWZCYrlOVnpij4JmbmaWgqVCvUctVycSG0G2FqNyKk3Yu5qDQvipPj2oS-9TdTBVgSGAE
333fred
333fred5d ago
(If you try that out, make sure you turn on the experimental language services in options)
333fred
333fred5d ago
No description
jjones
jjones5d ago
currently it has syntax highlighting only, semantic highlighting is coming right after I merge this intellisense improvements branch 🙂
ero
eroOP5d ago
didn't know there's a difference but that makes sense actually my main goal was really to have one app which can do everything a merging of sharplab and godbolt
jjones
jjones5d ago
that's my goal too 😄
ero
eroOP5d ago
and even sicker if there's a vscode extension
jjones
jjones5d ago
what is sharplab missing that godbolt has?
ero
eroOP5d ago
in godbolt, you can choose the runtime for the asm and the asm is also more accurate let me show an example so like coreclr and mono and whatever
jjones
jjones5d ago
I was investigating asm support too, but it would be very complicated to do in wasm; so I plan to create a MAUI hybrid version of the .NET Lab where it will be much easier (since it will run on full .NET)
ero
eroOP5d ago
No description
No description
ero
eroOP5d ago
left is sharplab of course
Angius
Angius5d ago
A side note, but I never heard of Godbolt, and they seem to advertise https://quick-bench.com/... I would love something like that for C#
ero
eroOP5d ago
never having heard of godbolt is crazy
jjones
jjones5d ago
being able to write quick benchmarks in .net lab is also on my todo list... it's a long todo list 😄
333fred
333fred5d ago
That was a motivating scenario for my developer sdk extension, but I haven't found the motivation to work on it like Jan has
ero
eroOP5d ago
i was thinking something like disasmo just have an option on a method/file/project to show the il/asm and it opens to the side man i'd be the happiest person in the world never again do i need to use the browser for it
333fred
333fred5d ago
I kinda have the IL part working, though I do think my extension may have broken recently and I need to find time to fix that https://github.com/333fred/compiler-developer-sdk/?tab=readme-ov-file#il-and-c-decompilation I never care about the asm, so it's even harder to find motivation to work on that Anyway, my hope is that we've convinced you to contribute to the existing things, ero, rather than trying to create your own
ero
eroOP5d ago
that looks awesome, but i'd use such an extension mainly for asm and decomp, il isn't a priority for me
333fred
333fred5d ago
I actually meant lab.razor.fyi
ero
eroOP5d ago
and i meant this
333fred
333fred5d ago
I know
ero
eroOP5d ago
i don't think i would have gotten far with this anyway, to be fair
333fred
333fred5d ago
But it looked like you were saying that as response to this As the entire chain of messages, not just that specific message
ero
eroOP5d ago
i can try and take a look at how much i can contribute to lab.razor.fyi, but honestly, roslyn would be higher on that list for me i'd prefer learning how that codebase works to contribute
333fred
333fred5d ago
Well, we're happy to help with that too
ero
eroOP5d ago
the tests are just so daunting actually idk why i said that everything is daunting in that codebase it's so big and i know so little about it
333fred
333fred5d ago
Sure, but I would actually say the tests are one of the best parts The tests are an incredible safety net
ero
eroOP5d ago
definitely, i wouldn't have it any other way
333fred
333fred5d ago
I can be pretty confident when I make big changes, because if I broke something important, there will near-certainly be a test that finds it
ero
eroOP5d ago
i'll just hijack my own thread and convert this into a roslyn good-first-issue help thread
333fred
333fred5d ago
ide or compiler?
ero
eroOP5d ago
let's see which one of my own issues i wanna do err, probably ide most of my issues are ide
333fred
333fred5d ago
Can't help you as much there, and Cyrus is currently on vacation so he may not be available for the next couple of days
ero
eroOP5d ago
oof
333fred
333fred5d ago
But I can try
ero
eroOP5d ago
i love you guys, can i just say that like the whole compiler team i have this one open https://github.com/dotnet/roslyn/issues/75113 but that doesn't actually appear compiler related? that looks ide related to me
333fred
333fred5d ago
Assuming Rekkon was correct about that investigation, they're indeed right that it's non-trivial
ero
eroOP5d ago
this one too, looks to be in the correct area, but so much more difficult https://github.com/dotnet/roslyn/issues/75664
333fred
333fred5d ago
The IDE gets its information from the compiler. In this case, there appears to be no information to get
ero
eroOP5d ago
oh, huh
333fred
333fred5d ago
Honestly? This might be easier, but I don't know what we're currently accepting for collection expression optmization changes. @rikki or @jaredpar might know more
ero
eroOP5d ago
i had another issue the other day, put a code snippet aside, and then closed my ide without saving... it had to do with renaming some generic parameter
333fred
333fred5d ago
Adding new collection expression optimizations is actually fairly well contained
ero
eroOP5d ago
i'm so mad that i didn't create an issue immediately
333fred
333fred5d ago
That would be squarely IDE codebase, 100%
ero
eroOP5d ago
absolutely, like i said, most of my issues are
333fred
333fred5d ago
Well, the two you've linked so far aren't 😄
ero
eroOP5d ago
wanted to show the only 2 open compiler issues is have 🥲
ero
eroOP5d ago
No description
333fred
333fred5d ago
If I had to guess, https://github.com/dotnet/roslyn/issues/75289 wouldn't be hard
GitHub
Use explicit type instead of 'var' emitted on enum value assignme...
Version Used Compiler: 4.12.0-3.24470.4 (d799b05) .NET: 9.0.100-rc.1.24452.12 Visual Studio Code: 1.93.1, 38c31bc77e0dd6ae88a4e9cc93428cc27a56ba40, x64 C# Extension: v2.49.25 C# Dev Kit Extension: ...
ero
eroOP5d ago
from cyrus' comment, i assumed this was not going to be changed
333fred
333fred5d ago
That's not how I read it
ero
eroOP5d ago
oh my god
333fred
333fred5d ago
I read it as "yeah, I agree"
ero
eroOP5d ago
i keep reading it as "this does not" for whatever reason like for so long i thought, ok, i don't get it, but you do you
333fred
333fred5d ago
If he didn't think it would be good, he'd have closed it out
ero
eroOP5d ago
that looks fairly easy indeed
333fred
333fred5d ago
77181 also doesn't look too bad, you just need to learn about trivia And that one is explicitly marked as help wanted
ero
eroOP5d ago
i've opened something similar in the past, where formatting would remove leading whitespace from one line could be a similar fix
333fred
333fred5d ago
Sounds similar indeed
sanic
sanic5d ago
I’m happy to review collection-expr optimizations, but for anything ambitious I do first want the contributor to share a fairly specific plan for how they expect codegen to change and ideally a microbench of the old and expected new codegen. For example, to motivate “use ROS for List<T> = [consts]”, some microbenching of list creation in the current and new ways, with various list lengths, to show where we actually think the right point is to kick in such an optimization. Actually implementing that one should not too be bad, we already know how to make a ROS pointing to consts, we just have to CopyTo the span of the list elements.
sanic
sanic5d ago
This particular time of the release cycle is busy so I would possibly need a few weeks to be able to get a review in.
ero
eroOP5d ago
i'd have to fine grain it to find a more optimal count, but it is < 100 so probably ~32
sanic
sanic5d ago
Nice! I would like to see how much worse is copyto with very small collections (size 1, 2, 4), and I would also like to see the margin of error reported by benchmarkdotnet in all cases. I’m expecting you are about right, enabling this somewhere between 10-32 elements will be the way. But just knowing the characteristics of more sizes will be helpful.
ero
eroOP5d ago
i see. i explicitly hide the Error column in my benchmarks. is that wrong? do you prefer hiding StdDev? or hide neither? do you believe the benchmarks themselves are adequate? or am i doing something wrong
sanic
sanic5d ago
I’ll take a look at the actual benchmark code when I get back to my pc
ero
eroOP5d ago
thanks
333fred
333fred5d ago
Yes, it is wrong to hide error. You cannot judge whether a result is significant without that column
ero
eroOP5d ago
i see. i believe i thought stddev did what error does i'm not sure of the difference
333fred
333fred5d ago
Error is basically a +/-. The only way to say that a result is significant is to use the error column to take the worst possible "better result" (ie, better result + error) and compare with the best possible "worse result" (ie, worse result - error). If that overlaps, then the result is not significant stddev is about how spread out the values tend to be: if you were to plot each individual result on a graph, std dev would tell you how clustered they are IE, is it wildly all over the place, or is it mostly clustered right around the average, with just a few outliers Both values are important to determining the significance of a result, but (imo) error is more so As a concrete example, let's say that you have operation a and b. Operation a takes 7 nanoseconds, with an error of .6 nanoseconds. Operation B takes 8 nanoseconds, with an error of .4 nanoseconds. The "better" result is a, so we look at the worst possible a value, 7 + .6 = 7.6 ns. The "worse" result is b, so we look at the best possible value, 8 - .4 = 7.6 ns. Those values overlap, so there is likely no gain, but to confirm we can look at std dev: if the std dev for both operations is .01ns, then that means the best/worst here is real outlier, so maybe there actually is a perf improvement, but it's hard to say without more benchmarking
jaredpar
jaredpar5d ago
We are a bit under the water right now. Later on there might be more appetite for this. But at the same time,for optimizations, we usually watn a runtime person to sign off on the direction. At the least they need a heads up on what we are betting on
ero
eroOP5d ago
We are a bit under the water right now.
that's the impression i have as well
| Method | Mean | Error | StdDev |
|----------------------------------- |----------:|----------:|----------:|
| Initialize_CollectionExpression_1 | 9.377 ns | 0.2276 ns | 0.2795 ns |
| Initialize_CopyTo_1 | 8.402 ns | 0.0878 ns | 0.0778 ns |
| | | | |
| Initialize_CollectionExpression_2 | 8.831 ns | 0.0823 ns | 0.0770 ns |
| Initialize_CopyTo_2 | 8.818 ns | 0.0550 ns | 0.0487 ns |
| | | | |
| Initialize_CollectionExpression_4 | 8.960 ns | 0.2273 ns | 0.2526 ns |
| Initialize_CopyTo_4 | 9.264 ns | 0.2342 ns | 0.2506 ns |
| | | | |
| Initialize_CollectionExpression_8 | 9.774 ns | 0.1609 ns | 0.1344 ns |
| Initialize_CopyTo_8 | 9.952 ns | 0.2293 ns | 0.1914 ns |
| | | | |
| Initialize_CollectionExpression_16 | 11.337 ns | 0.1279 ns | 0.1068 ns |
| Initialize_CopyTo_16 | 10.934 ns | 0.0969 ns | 0.0906 ns |
| | | | |
| Initialize_CollectionExpression_32 | 14.714 ns | 0.0594 ns | 0.0496 ns |
| Initialize_CopyTo_32 | 13.555 ns | 0.3444 ns | 0.9882 ns |
| | | | |
| Initialize_CollectionExpression_64 | 25.026 ns | 0.6344 ns | 1.8505 ns |
| Initialize_CopyTo_64 | 18.040 ns | 0.4109 ns | 0.6751 ns |
| Method | Mean | Error | StdDev |
|----------------------------------- |----------:|----------:|----------:|
| Initialize_CollectionExpression_1 | 9.377 ns | 0.2276 ns | 0.2795 ns |
| Initialize_CopyTo_1 | 8.402 ns | 0.0878 ns | 0.0778 ns |
| | | | |
| Initialize_CollectionExpression_2 | 8.831 ns | 0.0823 ns | 0.0770 ns |
| Initialize_CopyTo_2 | 8.818 ns | 0.0550 ns | 0.0487 ns |
| | | | |
| Initialize_CollectionExpression_4 | 8.960 ns | 0.2273 ns | 0.2526 ns |
| Initialize_CopyTo_4 | 9.264 ns | 0.2342 ns | 0.2506 ns |
| | | | |
| Initialize_CollectionExpression_8 | 9.774 ns | 0.1609 ns | 0.1344 ns |
| Initialize_CopyTo_8 | 9.952 ns | 0.2293 ns | 0.1914 ns |
| | | | |
| Initialize_CollectionExpression_16 | 11.337 ns | 0.1279 ns | 0.1068 ns |
| Initialize_CopyTo_16 | 10.934 ns | 0.0969 ns | 0.0906 ns |
| | | | |
| Initialize_CollectionExpression_32 | 14.714 ns | 0.0594 ns | 0.0496 ns |
| Initialize_CopyTo_32 | 13.555 ns | 0.3444 ns | 0.9882 ns |
| | | | |
| Initialize_CollectionExpression_64 | 25.026 ns | 0.6344 ns | 1.8505 ns |
| Initialize_CopyTo_64 | 18.040 ns | 0.4109 ns | 0.6751 ns |
looks like 8 is already close, and from 16 onwards, CopyTo is definitely faster would you like it even more fine tuned between 8 and 16? benchmark code is just
[Benchmark(Baseline = true)]
[BenchmarkCategory("8")]
public List<int> Initialize_CollectionExpression_8()
{
return
[
00, 01, 02, 03, 04, 05, 06, 07
];
}

private static ReadOnlySpan<int> _span8 =>
[
00, 01, 02, 03, 04, 05, 06, 07
];

[Benchmark]
[BenchmarkCategory("8")]
public List<int> Initialize_CopyTo_8()
{
List<int> list = new(_span8.Length);
CollectionsMarshal.SetCount(list, _span8.Length);

Span<int> span = CollectionsMarshal.AsSpan(list);
_span8.CopyTo(span);

return list;
}
[Benchmark(Baseline = true)]
[BenchmarkCategory("8")]
public List<int> Initialize_CollectionExpression_8()
{
return
[
00, 01, 02, 03, 04, 05, 06, 07
];
}

private static ReadOnlySpan<int> _span8 =>
[
00, 01, 02, 03, 04, 05, 06, 07
];

[Benchmark]
[BenchmarkCategory("8")]
public List<int> Initialize_CopyTo_8()
{
List<int> list = new(_span8.Length);
CollectionsMarshal.SetCount(list, _span8.Length);

Span<int> span = CollectionsMarshal.AsSpan(list);
_span8.CopyTo(span);

return list;
}
333fred
333fred5d ago
I would say it's questionable until somewhere between 32 and 64
ero
eroOP5d ago
Questionable due to how close the results are? I'll wait for rikki's input, but I see what you mean
333fred
333fred5d ago
Yes. Best compared to worst is within hundreths of a nanosecond 8 and below we can very definitively say is not significant. 16 and 32 are questionable. 64 is a clear improvement

Did you find this page helpful?