Live data from Hacker News

Pony – High-Performance Safe Actor Programming

ponylang.io

141–150 of 159 posts

Re: Pony – High-Performance Safe Actor Programming

#141
Three things I definitely dislike about this language:

- Error handling. Uninspectable, untyped errors that still must be declared and caught is just a total waste of an error system. It's not actively harmful, since you can just use primitive unions instead, but it's still a waste. If it's a recoverable error, it should have types and be inspectable so you can recover from it; if it's unrecoverable, it shouldn't have to be caught or declared.

- The file-based package resolution scheme. It is an absolute blight on any language that has it.

- The lack of function overloading. I excuse this in Rust because Rust trait implementations have their own namespace, so nothing conflicts, but if there are two Pony traits with the same function with different types or a different arity, there doesn't appear to be a way to implement both on the same class.

Re: Pony – High-Performance Safe Actor Programming

#142

Earlier quoted context omitted.

I didn’t say that Pony prevents race conditions. I agree that Pony (nor indeed any language) prevents race conditions.

I misread then. Though you did ironically just say that pony does prevent race conditions :P

grrrrr

Re: Pony – High-Performance Safe Actor Programming

#143
post #129

Earlier quoted context omitted.

At least with Rust, very few domains involve so much parallelism that one benefits from the overhead that the borrow checker adds to the development process. And many times the borrow checker is completely inadequate at preventing race conditions (frequently the case with distributed computing). Of course, Rust can recoup those losses elsewhere, by having better tooling or competing in domains where performance matte…

Rust's borrow checker is not only for multi threading and memory safety. It allows someone designing an API for any kind of data structure to guarantee that the user is using it correctly, by making their code not compile when they are using it incorrectly (basically what any type system provides, but fancier). What you call borrow checker overhead, some would call fixing problems before they occur.

You’re right that there are other benefits of Rust’s type system beyond precluding data races, but even still, the overhead of Rust is too steep to make it a good fit for the kinds of applications I write.

Re: Pony – High-Performance Safe Actor Programming

#144
post #116

Earlier quoted context omitted.

`Arc >` is not a shared mutable state. You cannot have two mutable reference at the same time. To mutate stuff inside the mutex, you got to hold the mutex, which guarantees that there are only one mutable reference at any given moment. `RefCell` is one "escape hatches".

Worth noting that RefCell still enforces single-mutable-reference, it just does so at runtime . It lets you do things that could never be verified statically, but if you ever actually violate the condition, you'll get a panic (which is still better than memory unsafety).

Should be noted that this only works across threads.

Nothing can be assumed regarding data races if it happens to be a shared value of some sort modified via IPC or other kind of APIs across multiple processes accessing the same resource.

Re: Pony – High-Performance Safe Actor Programming

#145
post #94

Earlier quoted context omitted.

Pony and Rusts' solutions to the concurrency problem are almost identical - forbid shared mutability through the type system. In what way are they very different?

Rust is essentially C++ with restrictions that make threads safer. Pony is a completely new language based on the actor model where "threading" is a first-class operation and the type system is formally designed to make guarantees that make threads safer. Pony really wants you to think differently about your problem and solution.

> Rust is essentially C++ with restrictions that make threads safer.

And saner defaults for type safety.

As much as I enjoy C++, the safety defaults due to backwards compatibility are mostly wrong.

Re: Pony – High-Performance Safe Actor Programming

#146

Earlier quoted context omitted.

At least with Rust, very few domains involve so much parallelism that one benefits from the overhead that the borrow checker adds to the development process. And many times the borrow checker is completely inadequate at preventing race conditions (frequently the case with distributed computing). Of course, Rust can recoup those losses elsewhere, by having better tooling or competing in domains where performance matte…

> And many times the borrow checker is completely inadequate at preventing data races (frequently the case with distributed computing). The borrow checker (in safe rust) always[0] prevents data races. It can't, however, prevent race conditions (but neither can pony do[1]) [0] https://doc.rust-lang.org/nomicon/races.html [1] https://www.ponylang.io/faq/#data-race

> The borrow checker (in safe rust) always[0] prevents data races.

As long as those data races originate from threads, it cannot prevent data races across processes, for example:

- Modifying the same file location

- Modifying the same table cell without transactions

- Talking to the same IO port

- Data sharing between CPU and GPU

Re: Pony – High-Performance Safe Actor Programming

#147
post #90

Earlier quoted context omitted.

In Java, the “each public class is in its own file named after the class” rule is enforced by the compiler and there’s no switch to disable this behavior.

I guess that shows how uniformly the convention is followed that I wasn't aware of that! I remember finding a class in a PR that had been renamed without renaming the file, and we were surprised it compiled. It must not have been a public class. $ echo "class Bar { }" > Foo.java $ javac Foo.java $ ls Bar.class Foo.java $

That is not a public class.

If you don't specify any access modifier, it is the same as internal in .NET.

Re: Pony – High-Performance Safe Actor Programming

#148
post #97
post #93

Huh. This is something I don't think I agree with: "Incorrectness is simply not allowed. It’s pointless to try to get stuff done if you can’t guarantee the result is correct." I'm sure that's true in some domains, but I think they're pretty narrow. E.g., if I were building an internal API that managed money, I might buy that. But I think the vast bulk of software is essentially exploratory. We ship something minimal…

For reference, you're pulling that quote from https://www.ponylang.io/discover/#the-pony-philosophy Clearly, the sentence you quote is making an unqualified absolute statement, which are usually easy to pick apart and tear down. After reading the whole philosophy, I'm not really sure what they mean by "guarantee" and "pointless" here. I doubt they're saying that all programming in "unsafe" languages is "pointless." I…

Sure, and as I said, I think their get-stuff-done philosophy must apply in pretty narrow contexts if they prioritize correctness that strongly.

At least for humans, correctness and consistency are very difficult, and therefore very expensive to achieve except under narrow conditions. Mainly we don't bother. That's part of why dynamic languages like Python and Ruby are so popular. Correctness takes a back seat to convenience.

There's nothing wrong with Pony making these choices. Let a thousand flowers bloom. But when I look at a new language or tool, my first question is, "What kinds of problems might it be good for?" From this quote, plus a number of other things, it's pretty clear to me that they've chosen a relatively narrow domain, one I do very little work in.

Re: Pony – High-Performance Safe Actor Programming

#149
I spent a few minutes on the site trying to find a code sample without launching into the playground... Even the “Getting Started” and “Tutorial” pages just repeat the features from the front page with zero code.

I’ve seen this from other new languages lately. Please, study the Swift or TypeScript sites!

Re: Pony – High-Performance Safe Actor Programming

#150
post #136
post #61

Earlier quoted context omitted.

What issues did you run into on the JVM with Java/Scala? I spent 5 years working up and down the entire akka stack so I'm curious to learn from your point of view. Also did you try akka typed or classic?

I'm not the parent poster but I'll have a go. Please feel free to correct me if I've got parts wrong, I'm hoping to learn something too. In other languages, lets say Erlang as an example, actors themselves do not have concurrency concerns. The receive loop/handler just executes everything as though it's single threaded. The code is very easy to reason about. It also applies backpressure in that if your synchronous lo…

Also, serialization and object versioning challenges. I think I mentioned this in another comment but the lack of static typing in erlang/elixir tends to fence your composition model to where these sorts of problems are elided or explicitly handled in code.

But AFA Async, I guess I have thoughts.

> With akka actors, instead of just dealing with the actors and actor pools, they suggest you make actors non-blocking. The way you do this is with Futures.

I don't know how things work in JVM/Akka specifically but on the .NET side the use of async is 'Tolerable'. We have a ReceiveActor that lets you wire up your message type to an async method and it handles all of the stashing/etc internally until the future completes. You have to type a couple extra words but they're the same words you have to type everywhere else you use async.

With the other sugar .NET gives you it's really not too bad. In the system our team built, the main piece of 'blocking' code we have is a call to a C library that does not have any real 'async' bindings. The rest were things like loggers, although typically if 'logging' is blocking either you're logging too much or the rest of the system is probably not in a good state anyway. (edit: FWIW, the 'block' is 80-100ms and constant, we can live with it for our case)

> How do you identify the bottlenecks of the system? Maybe your execution context is full - actually I'd love to know how people debug their execution contexts in general.

Interestingly, Akka.NET doesn't quite have this sort of problem.The default Dispatcher (At least that's what we call the base type) runs on the .NET Thread pool which has a good degree of 'self tuning', and you can peek at the number of threads vs what the pool maxes out at with 4 lines of code or so. However in .NET we have 'SynchronizationContexts' which result in the need for special dispatchers for things like a UI update (as most UI frameworks have their own context for handling UI).

> One of the benefits of this arrangement is if something is going slowly you can order the list of actors by biggest mailbox and you can see where your bottleneck is.

You could probably hack together something off of akka visualmailbox [0] as it shows how to grab metrics from 'inside' a mailbox. I did a toy port to .NET and while on that side I had to do a lot of 'configuration' and still need to create metrics collecting mailboxes for all the types (we don't have traits...) but it seemed to actually work not-bad.

Post reply on HN