[External] : Re: jstack, profilers and other tools

Alex Otenko oleksandr.otenko at gmail.com
Sun Jul 24 13:05:44 UTC 2022

I am not sure what made you think I am fighting for async style everywhere.
I am merely pointing out that some tasks are harder to solve in sync code -
and impossible to solve, if you rely on library/built-in that isn't doing
what you want. Like, if JDK doesn't expose a mechanism to prioritize reads,
you can't solve the problem of reading fewer requests completely vs more
requests partially.

Also, I am not clear why you dismissed the allocation problem by just
saying IO buffering is the same. The allocation problem is that user code
allocates before read(byte[]) is called. This is the same in both sync and
async code. The difference is that in async code the lifespan of the
allocation is shorter - we read only read-ready channels, and those that
aren't ready return quickly. In sync code the buffer remains allocated for
a long time - even seconds, if that's what the connection reuse pattern is
on the client side.

On Sat, 23 Jul 2022, 02:00 Ron Pressler, <ron.pressler at oracle.com> wrote:

> > On 23 Jul 2022, at 00:06, Alex Otenko <oleksandr.otenko at gmail.com>
> wrote:
> >
> > I am familiar with the bijection between types and continuation-passing.
> There is however a barrier. Who does the thing of interest in each of the
> styles: the caller or the callee.
> >
> > In terms of type theory it doesn't matter; both styles have the same
> power. In terms of software engineering it does matter. It is impossible to
> plug custom logic in a library that you import, unless a mechanism is
> planned at design time, and built in - most commonly a bunch of
> configuration options to tweak a parameterised algorithm; not really the
> ability to implement arbitrary algorithms that the theoretical bijection
> requires. So in practice you are limited to doing only things a caller can
> do.
> >
> > Same for allocation. It is doable to get the same behaviour as in async
> API, but it is not what InputStream.read(byte[]) does - the method
> signature forces you to allocate and wait. And there is no mechanism to
> tell the blocking API to read 10k of 100 requests instead of 100 bytes of
> 10k requests. It's doable, but it is not there.
> No, all that is simply incorrect. The customisability of synchronous code
> is at least as ergonomic and flexible as for async code if not more so
> (because Java is built around synchronous primitives, and its basic
> composition operators are made for synchronous primitives), and the I/O
> buffering primitives provided by the JDK are no different between
> synchronous and asynchronous.
> I feel like you’re trying to find some justification for your aesthetic
> preference for asynchronous code, and there’s really no need. If you enjoy
> it more, and you don’t need the observability support from the runtime — by
> all means keep using it. Our goal isn’t to get fans of asynchronous code to
> abandon using it. It is to give the same benefits to those who prefer using
> synchronous code, and we can even go further because it is a better fit for
> the design of the Java platform and so that’s where we can support the code
> better, both in the runtime and the language. But if you like async better
> — use async.
> But while we’re in the weeds, there are some interesting differences re
> memory usage, although they are not fundamentally about sync vs async, but
> some technical specifics of the JDK and how virtual threads are
> implemented. This might be of interest to the curious.
> Whether you use the async or sync style, there’s need to pass data from
> computation done before the call to computation done after. In Java, the
> async style normally requires allocating a new object to do that, while
> sync reuses the same mutable stack. Hypothetically, async code could
> implement such a mutable stack manually, but in Java it is difficult,
> because, unlike in C, heap objects cannot switch between storing pointers
> and primitives in the same memory cell. Stacks are designed to allow that
> thanks to special GC protocols, that were adapted for virtual threads.
> On the other hand, for simplicity and performance reasons in the JIT
> compiler, the way data is stored in the stack is wasteful (so fewer but
> bigger objects are allocated). We’re now working on making it more compact
> in the case of virtual threads.
> — Ron
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/loom-dev/attachments/20220724/6f78bf6c/attachment.htm>

More information about the loom-dev mailing list