Hacker News new | past | comments | ask | show | jobs | submit login

The basic issue was that the coroutine package was segfaulty and maintained by a man so lovely to interact with that the node.js core team eventually invented libuv (to replace his ev library) primarily so they never had to talk to him again.

Perl now has http://p3rl.org/Future::AsyncAwait which is (like any async/await system) a bit more restricted than a full coroutine but works beautifully.

If you threw a github repo up somewhere I can think of a few people who might be interested in trying to update it to more recent+reliable perl tech.




Thanks for the suggestions!

But I've found Coro highly reliable and effective, including under stressed and complex loads, for about 6 years. Never found it segfaulty. It also performed well, and the API design always impressed me with its cleanliness and good documentation.

Also I make extensive use of coroutine-local variables (like `thread_local` in C11) which operate at the same speed as normal `my` lexicals. I.e. as fast as possible. It's just a good way that ordinary non-async modules can be trivially made async-safe, without performance loss, and without becoming tied to async or not-async (they become equally flexible for both uses, which is valuable). (The module to make them run that fast isn't public, but the API it relies on to work is part of Coro. `Future::AsyncAwait` doesn't provide the necessary API at the moment.)

> Perl now has http://p3rl.org/Future::AsyncAwait which is (like any async/await system) a bit more restricted than a full coroutine but works beautifully

I'm not convinced. Future::AsyncAwait is a different paradigm, and doesn't do the things I find Coro useful for.

Async/await has the "function colour" problem - every module that might logically "block" has to be re-engineered with a new, async version of the same module. Same applies to any function which might call another to any depth in the call graph which then "blocks". People have argued that the "function colour" problem with async/await isn't really a problem. I'd argue that it's fine if you've designed around it from the start and you don't intend to use code in both async and non-async environments.

That re-engineering can be done, but it's a massive change to existing modules, and then you end up with something that can only be used in an async/await program.

Whereas Coro is non-invasive. I use the same modules in an async server or in a classic process-forking server (without loading Coro and no concerns about async issues), as well as standalone processes (scripts). I choose appropriately depending on the service characteristics (e.g. async is poorly suited to some kinds of loads such as computationally heavy request processing). Also for some things it's good to have the confidence that comes from not loading any fancy stuff, e.g. in security code and standalone scripts.

For that dual-use functionality, as far as I can tell with Future::AsyncAwait I'd need to write two separate versions of most things.

It turns out a lot of things might call something that, via a deep and opaque call chain, might block somewhere. E.g. any code that loads a config file when it's first run. Anything that uses a template, and calls out to a template compiler. Anything that compiles and loads code lazily. Anything that does something as trivial as stat() on a file.

In practice for my web stuff that means nearly everything (as you can imagine from my GP comment). I also make heavy use of JSX-ish templates instead of custom Perl code. It's just cleaner, and they can be targeted to other languages, even compiled to C for speed. Template components end up inheriting the same async properties as the server they are running in. A page may refrence subresources, microservice calls, data fetches or file reads. All fetched or calculated in parallel (calling other services or using multiple cores if necessary), which is good for latency.

There's also a software engineering impact. As soon as you get deep into complex logic like filesystems, and especially with memory allocation inside those, which triggers nested filesystem access, it's just too much work to engineer everything in an async state machine way. That's why the Linux kernel was unable to do correct asynchronous I/O through AIO functions for many years, and that's why everything end up choosing threads instead of AIO in userspace too: libuv that you mentioned is a great example!

> update it to more recent+reliable perl tech

I think "reliable" is misleading. Coro is highly reliable (for me anyway), while Future::AsyncAwait has documented gotchas.

For "more recent", the Perl community has picked its path. In my view it's a less useful path, and I'm disappointed Perl core didn't choose to implement a coroutine mechanism. But it didn't.

With Coro all the modules just work without anything Coro-specific in them. (Just a few coro-local-data annotations, which are ignored when Coro isn't loaded.) It's neat!

As I use the same code in async and non-async contexts, I really don't see me using Future::AsyncAwait and writing two versions of each module.

> If you threw a github repo up somewhere I can think of a few people who might be interested

I never did get that framework to a point where I'm happy to publish, because it's entangled with commercial and private code. Cleaning up the separation seemed like a goal once, but I think I'd be wasting my time now. It's a great shame when you have a big personal library of Really Useful Modules, but sometimes you just have to start again. The ideas live on!


> But I've found Coro highly reliable and effective, including under stressed and complex loads, for about 6 years.

Had that been a more universal experience things might've been different.

I did once try and see if I could get a stripped down version to try and push into core but at the point where I'd deleted 90% of the code and the entire test suite still passed I realised that getting a reliable stripped down version was going to be a problem.

> Also I make extensive use of coroutine-local variables

I've been using Syntax::Keyword::Dynamically where I need that.

> For that dual-use functionality, as far as I can tell with Future::AsyncAwait I'd need to write two separate versions of most things.

I tend to write async by default and then for blocking code I call a blocking version of the API.

> I think "reliable" is misleading. Coro is highly reliable (for me anyway), while Future::AsyncAwait has documented gotchas.

I'll take documented gotchas over undocumented weird shit and an author who refuses to use a bugtracker and has a track record of deleting features if he doesn't like how people are using them.

> With Coro all the modules just work without anything Coro-specific in them.

Or at least they used to. The author no longer supports the past five years or so of perl releases so there's no combination of supported perl and supported Coro that exists anymore :(




Consider applying for YC's Spring batch! Applications are open till Feb 11.

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

Search: