carrier local

Thomas May tmay at clearwateranalytics.com
Fri Apr 3 12:30:31 UTC 2020


Hmm, ok, makes sense.

I was thinking maybe something like the following might work.

class CarrierLocal<T> {
    private T state;
    private final Supplier<T> stateSupplier;

    CarrierLocal(Supplier<T> stateSupplier) {
        this.stateSupplier = stateSupplier;
    }

    public <U> U use(Function<T, U> action) {
        if (state == null)
            state = stateSupplier.get();
        U result = action.apply(state);
        if (state != null && result == state)
            throw new IllegalArgumentException("You must not return internal state");
        return result;
    }
}

(Obviously eliding over how state is associated with a  given thread)

This would mostly prevent you from accessing state outside.  However, you'd need machinery in place to either make sure `park` in the action method either throws or causes the current fiber to be rescheduled on the same carrier thread.

IDK, though, the restrictions around that `action` function would be weird and potentially non-intuitive.

-----Original Message-----
From: Alan Bateman <Alan.Bateman at oracle.com>
Sent: Friday, April 3, 2020 1:32 AM
To: Thomas May <tmay at clearwateranalytics.com>; loom-dev at openjdk.java.net
Subject: Re: carrier local

////////This email is from an external source. Please ONLY open links and attachments from trusted sources////////


On 02/04/2020 21:05, Thomas May wrote:
> LongAdder would be a good example where you'd want carrier local storage rather than thread local.  Having it ThreadLocal would allocate more memory than necessary.
>
> Another example is SimpleDateFormat.
>
> In fact, I'd think whenever you are using ThreadLocals to avoid synchronization you probably would be happy using carrier local instead of ThreadLocal.
>
SimpleDateFormat is a good example to discuss as an instance is expensive to create and it's not thread safe. It's also not too hard to find code that caches an SimpleDateFormat instance in a TL.

The intention is that you can cache a SimpleDateFormat in a TL and access it without synchronization as before. Yes, this would be a lot of memory with 1M threads. If there was an unsafe like method to get a reference to the carrier thread's TL then you would have to synchronize, consider this:

SimpleDateFormat format = <SimpleDateFormat object cached by carrier thread local> format.format(...);
socket.read(...)       // scheduling point, may park
format.format(...)

If several virtual threads execute this at, or around, the same time and you'll quickly see SimpleDateFormat being accessed from different kernel threads without synchronization, oops!

A good migration path for ThreadLocal<SimpleDateFormat>, to reduce memory usage, is to move to java.time.format.DateTimeFormatter. It's immutable and thread-safe, and faster to create too.

-Alan





________________________________

NOTICE: This e-mail message, together with any attachments, contains information of Clearwater Analytics and/or its affiliates that may be confidential, proprietary copyrighted and/or legally privileged, and is intended solely for the use of the individual or entity named on this message. If you are not the intended recipient, and have received this message in error, please immediately delete it. The information we provide is from sources Clearwater Analytics considers reliable, but Clearwater Analytics provides no warranties regarding the accuracy of the information. Further, nothing in the email should be construed as legal, financial, or tax advice, and any questions regarding the intended recipient’s individual circumstances should be addressed to that recipient’s lawyer and/or accountant.

Clearwater Analytics, 777 W. Main St, Boise, ID 83702
If you prefer not to receive emails from Clearwater Analytics you may unsubscribe<https://clearwater-analytics.com/unsubscribe>.


More information about the loom-dev mailing list