Hacker Newsnew | past | comments | ask | show | jobs | submit | _cdho's commentslogin

https://aws.amazon.com/blogs/compute/using-amazon-rds-proxy-...

> Your function code is cleaner, simpler, and easier to maintain.

I don't think your post covers the nuances. "Not a correct implementation"? We weren't trying for lowest latency, we were trying for highest reliability / simplest code / easiest to test. How do you test that your reused connections handle the "timed out right as next request comes in" case?


I mean not correct in the literal sense. It's not about reliability nor simplicity nor testability - the code is wrong. It has a bug. The code is written without understanding that lambda containers can be re-used, thus, it's exhausting a finite resource unintentionally.

You handle the "timed out right as next request comes in" case by memoizing the connection in a variable and checking if it's null in the handler. If it is, re-establish the connection.


Hmm, I spent >10 years with Python and on large/important apps it's hard to refactor and slow. (PS they're still using Python 2 as well). I want to pivot to C# on Linux / .Net Core.


That wouldn't be too bad. I'm over Windows. More specifically I'm over enterprise development using Windows. C# is a great language.


Hi, author here. Thanks for the kind words!

I ported the static site generator for patternedpom.com (sells handmade cards) from Python to C# without changing any layout or styling (PS I don't claim to be a frontend person). It was a code port only. 1000 LOC of C#, and it took me two weeks.

I am happy with the result code - The classes are immutable (auto properties / read only collections)[1], LINQ is a very suitable replacement for list comprehensions, and it's faster than the python.

Razor Templates are very nice - I have an outer layout file and an inner template for each page. I think they came out very cleanly, and I can do LINQ inside of them[2]. Obviously you can do similar things with jinja templates, but razor templates won't compile if something is wrong / doesn't match what the model exposes (yay for catching bugs early). And you can still pass a "dynamic" type object if you want python like behavior (that throws an exception on unknown property).

The "backend" is a google spreadsheet (using their .NET SDK) and some CommonMark markdown files. So it's not doing anything dynamic (yet, I'm almost done adding digital purchases using AWS Lambda / PayPal IPN, which would be a new feature for the site). And it syncs using AWS's S3 .NET SDK.

I don't think it was actually that many more lines of C# compared to python, in any case it's worth it for me. I am tired of using scripting languages for things other than, well, scripts. I hope Microsoft doesn't break things on me in a few years (fingers crossed).

That said... let's look at some other issues.

- vscode is ok. not perfect, probably some bugs (I get "file not found" popups from time to time that I have to close), but it's free. At least if you have the time to learn it. (I'm overwhelmed by all the configuration options really... and I'm trying to use the vim plugin which probably isn't helping my cognitive load)

- minor things: no generic ordereddictionary (casting isn't horrible though), no inplace collection sort() that takes a simple Key lambda, like the LINQ OrderBy() that copies.

- Library ecosystem - this is probably the #1 thing to check out. Does a good library exist, and does it run on .net core. Compared to Java or python, it's probably less, but do your own DD in advance. There is not even a standard command line option parser in .NET Core - so if it's anything you need outside of the core language, you need to build/buy/find it. It doesn't try to be a "batteries included" thing.

- Another example with libraries: I was looking at adding dynamic search with AWS lambda, but the .net lucene library seems to be an old port of the java library.

1. https://github.com/kjpgit/ppom/blob/master/source/SiteBuilde...

2. https://github.com/kjpgit/ppom/blob/master/source/SiteBuilde...


FWIW, Mono.Options is a decently widespread solution for command line parsing


Wow, a lot of interesting machinations. You've given me a few things to think about for sure. Thanks for the write-up!


My wife looked into instacart and we canceled after learning they don't provide business car insurance for their drivers. What a scam.


That is a good post and a valid criticism.

I'd say the more important concern with c# is to be careful you're not accidentally calling a "really blocking" function from an async method, or you will lose scalability. The lesser issue is the mundane task of changing all your function signatures in the chain to async.

I too would use Go if it didn't regress in every single area for me, other than concurrency, and make me sad.


What if your function signature needs to change and it's in public API used by thousands of call sites? The viral nature of it IMO is by far the biggest issue. That and much harder debugging / worse stack trace readability.


That is what I thought until I wrote the benchmark(s) in the post. I was surprised that even though I never called Task.Run, things were being run on 4-10 background threads.

It does use a threadpool scheduler by default for a console app. Yes, I could override that if I wanted to.


I believe that there is still only one thread executing your code. Now, depending on the SynchronizationContext that thread may change. If your I/O request completes on another thread, the default synch context for console apps just continue on that thread (avoids a context switch and thus more effective).

For UI threads (WPF, WinForms) it is essential that the code continues on the original thread. This the synch context used in WPF/WinForms will post the continuation on the original thread once it becomes available (thrugh the big message loop).

For ASP.NET threads, requests are processed from a thread pool. The ASP.NET synch context IIRC will schedule continuation on any ASP.NET managed thread.

So yes, you may see your code (esp. in console apps) executing on another thread after an async call, but that does not mean that .NET schedules your tasks on a thread pool. There is still only a single thread of execution at any one time, until you explicitly use a thread pool (e.g. Task.Run)


Yeah, I should clarify what I was saying. I wasn't calling Task.Run(), but I was doing:

    for (var i = 0; i < 1000000; i++) { 
        var unused_task_var = RunTaskAsync();
    }
    await RunMainMonitoringTaskAsync();
And I purposefully wasn't calling await on "unused_task_var". And this was doing what I wanted, running all those tasks on multiple background threads in the pool, as long as RunTaskAsync method itself yielded once early on in its function (to return control back to the for loop).

tl;dr If you call an async method and don't await on it, it will be parallelized - for a console app, at least.

Honestly, I don't find the MS docs on this to be that great. Not 100% sure I'm even doing it the right way here. Everybody says use Task.Run but that is for CPU bound tasks. I want to run a ton of IO waiting tasks.

edit: looks like I'm doing it right. See "Async Composition" @ https://blog.stephencleary.com/2012/02/async-and-await.html


Nod, iirc if you read through the specifications it is definitely Threads managed by a default pool as a default implementation. Depending on your needs trying to prematurely optimize can really distort how threads are used. I've seen this in a few prior projects, but forget some of the details.

In general it works pretty well until you need more than the defaults offer, then it becomes almost an exercise in frustration.


This is a good article which tries to explain how .NET works under the hood. https://blog.stephencleary.com/2013/11/there-is-no-thread.ht...


They have specified the lambda runtime. https://docs.aws.amazon.com/lambda/latest/dg/runtimes-api.ht...

Basically: your instance POSTS to an endpoint to get/reply to requests, one at a time.

I can't wait until you can specify that a lambda instance can handle a certain # of requests in parallel. Ex: things just blocked on IO/DB. That would make better use of your RAM.


Correct, hard to use TCP for 500K connections for a quick test when there are only 64K source ports which suffer from TIME_WAIT issues as bonus. It uses Unix Stream sockets.


Can you distribute your connections across 127.0.0.1, 127.0.0.2, 127.0.0.3, etc.? You've got the whole class A reserved as the loopback which should give you plenty of ports to work with.


64k ports is not a limitation for number of simultaneous tcp connections, in linux kernel ports are identified by (srcip,srcport,dstip,dstport)


It still will be amortized by your application's data. For example, reading and buffering actual messages. The benchmark literally just has a one byte "buffer" per connection.

I threw this benchmark together in a couple of hours pretty easily. The most annoying part was just measuring the RAM :-)

But yes, everything is a tradeoff. If you want safety, you pay more - either in RAM, or in cognitive load.


Ugh, I later realized I'm off by a factor of 4 because statm shows values in 4K pages, not 1K units.


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

Search: