<html><head><meta http-equiv="content-type" content="text/html; charset=utf-8"></head><body dir="auto"><div dir="ltr"></div><div dir="ltr">I disagree with that analysis. Javas original green threads were performed on a single thread. When they decided to use multiple threads they did not see the usefulness of green threads anymore. </div><div dir="ltr"><br></div><div dir="ltr">Java NIO was unnecessary - it could have been handled by bringing back green threads - instead every developer needed to essential create their own scheduling/IO framework to work with NIO. </div><div dir="ltr"><br></div><div dir="ltr">Only when Go demonstrated the viability of green threads did it come back to Java. </div><div dir="ltr"><br><blockquote type="cite">On Jul 5, 2023, at 8:54 AM, Paul Bjorkstrand <paul.bjorkstrand@gmail.com> wrote:<br><br></blockquote></div><blockquote type="cite"><div dir="ltr"><div dir="ltr"><div dir="ltr"><div>And why does Java not have green threads now? Because they did not live up to their promise - they were not efficient enough to supplant native threads (mostly due to the constraints at the time). Without an alternative (async/NIO), Java would have been relegated to what C/C++ developers had been saying at the time, that Java is a slow toy language. It would not have taken off as one of the most widely used enterprise languages.</div><div><br></div><div>Without the efficiency of NIO, we would not be having this conversation at all.</div><div><br></div><div>Yes, you have proven that it is not *necessary* to provide generators, (exposed) continuations, or custom thread scheduling. But that does not mean it is not and never will be desirable. In fact, green threads/virtual threads/userspace-scheduled threads got a boost, in no small part attributable to Ron (and his work on Quasar). If it weren't for someone saying "you know, I think I can make this better" or "I think I can find a use for this", green threads (in Java) would still be on the list of things Java got rid of, because they weren't practical/useful. Sure, new hardware had to also come along, but without the kind of thinking that brought about virtual threads, Java will stagnate into nothingness - as developers will move to more modern general-purpose languages that provide for their needs (and wants).</div><div><br></div><div>As I said, I am not advocating for the inclusion of generators right now either. The Java platform team has a budget that they can spend on features. Generators (to me) do not seem all that important right now, given that there are means of implementing them using the features of Java today. All that I ask is that we not stifle the innovative mindset just because they aren't that useful *right now*.</div><div><br></div><div>I will bring it back to the challenge I gave to those wanting generators, exposed continuations, or custom schedulers for virtual threads: show why it is needed!</div><div><br></div><div>Apologies to others for sidetracking the excellent conversation in this thread.</div><div> </div><div><div dir="ltr" class="gmail_signature"><div dir="ltr"><div>//Paul</div></div></div></div><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, Jul 5, 2023 at 6:45 AM Robert Engels <<a href="mailto:rengels@ix.netcom.com">rengels@ix.netcom.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="auto"><div dir="ltr"></div><div dir="ltr">One final note on this. Java could of had VT decades ago. It was the same “we need X because I like X - or X is popular” thinking that sent Java down the wrong path - rather than letting the engineers control the feature creep and design language changes that best matched existing design paradigms. </div><div dir="ltr"><br></div><div dir="ltr">Java started with green threads… :(</div><div dir="ltr"><br><blockquote type="cite">On Jul 5, 2023, at 6:34 AM, Robert Engels <<a href="mailto:rengels@ix.netcom.com" target="_blank">rengels@ix.netcom.com</a>> wrote:<br><br></blockquote></div><blockquote type="cite"><div dir="ltr"><div dir="ltr"></div><div dir="ltr">I claim the opposite - Java was polluted when async was added - VT brings Java back to the original design. </div><div dir="ltr"><br></div><div dir="ltr">As for the other elements - if you have a thread first + queue design you don’t need these other features as most were added in a similar vain to Javas async support.  Generators is one of them as I’ve proven. There is nothing a native implementation would provide over what I’ve delivered. VT are continuations. It is the same construct written in the existing language features. </div><div dir="ltr"><br></div><div dir="ltr">If you create a kitchen sink language you get fragmentation in the community and the code bases and needlessly complicate the tools - delaying the release of critical features. Look how many releases we’ve had and VT is still in preview. This is a direct result of Javas current complexity. Don’t make it more so. </div><div dir="ltr"><br><blockquote type="cite">On Jul 5, 2023, at 12:58 AM, Paul Bjorkstrand <<a href="mailto:paul.bjorkstrand@gmail.com" target="_blank">paul.bjorkstrand@gmail.com</a>> wrote:<br><br></blockquote></div><blockquote type="cite"><div dir="ltr"><div dir="ltr">Robert,<div><br></div><div>I can agree that Java/the JDK should not *focus* on features that are less broadly useful but, I challenge a statement you made at the very beginning of this thread:</div><div><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">I would fully avoid all of these isolated use case. Virtual threads solves the primary need for Java - thread per connection.<br><br>All of these other uses can be done in other languages - don’t pollute Java with less useful idioms that solves peoples need to not have to learn CS.</blockquote><div> </div><div><div dir="ltr" class="gmail_signature"><div dir="ltr"><div>Using this argument, Java didn't need virtual threads at all! They are a nicety to simplify *the code of* concurrent systems, akin to syntactic sugar.</div><div><br></div><div>We have had perfectly good, highly performant concurrent systems in Java for a very long time. We didn't *need* virtual threads to make it work. Sure, they are needed for thread-per-request, but thread-per-request is not needed to write concurrent systems.</div><div><br></div><div>Your argument "don’t pollute Java with less useful idioms that solves peoples need to not have to learn CS" could be easily extended to virtual threads too:</div><div><br></div><div>"Don't pollute Java with" a thread-per-request nicety to simplify the programming model for concurrent systems (e.g. HTTP servers). We already have NIO, selectors, and async programming models. Virtual threads only "solves people's need to not learn CS" by making it easier to write concurrent systems.</div><div><br></div><div>I can understand that *you* may not find generators particularly useful, but you are not the only user of Java (or the JDK). Yes, they *can* be written atop virtual threads as they are today (and you have provided a couple good examples of this, thanks!), but that does not diminish the value of generators (or primitives upon which to build generators) being provided by the JDK.</div><div><br></div><div>I wholeheartedly agree with Ron's message just prior to yours:</div><div><div> <br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">However, it’s important to remember that our priorities are primarily shaped by Java’s role as a *mainstream* platform and the demands of *mainstream* usages. In other words, what drives up the priority of the feature is not its hypothetical power but its potential use in mainstream applications because that’s where most of the value is, considering the majority of Java’s users.</blockquote><div><br></div><div>How does something become mainstream when it is a completely new thing not yet available? One way is by being evangelized, just like in this thread! Another way is to demonstrate the usefulness in a real life situation.</div><div> </div><div>Instead of dismissing the request without any kind of discourse, I would challenge those looking for continuations or generators in the JDK to show examples of how they are useful but either not possible or extremely difficult to build in Java today. Prove they are worth the engineering effort required to build them.</div><div><br></div></div>//Paul</div><div dir="ltr"><br><br></div></div></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, Jul 4, 2023 at 8:31 PM robert engels <<a href="mailto:rengels@ix.netcom.com" target="_blank">rengels@ix.netcom.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div><br><div><br><blockquote type="cite"><div>On Jul 4, 2023, at 6:28 PM, Attila Kelemen <<a href="mailto:attila.kelemen85@gmail.com" target="_blank">attila.kelemen85@gmail.com</a>> wrote:</div><br><div><div dir="ltr"><div dir="ltr">Robert Engels <<a href="mailto:rengels@ix.netcom.com" target="_blank">rengels@ix.netcom.com</a>> ezt írta (időpont: 2023. júl. 5., Sze, 0:48):<br></div><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="auto"><div dir="ltr"></div><div dir="ltr">I don’t believe any of those statements are true. Even if the language supported generators directly - they are still subject to gc. The JVM needs a way to release the generator and it’s backing resources. If it did that directly - like a destructor - when it goes out of scope it still wouldn’t be able to release the other resources. </div><div dir="ltr"><br></div></div></blockquote><div><br></div><div>It is not about being subject to GC or not. My claim is the following: With JVM implementation, it could be that:</div><div><br></div><div>Iterator is unreachable -> Continuation is unreachable -> Generator is unreachable</div></div></div></div></blockquote><div><br></div><div>This is exactly how my implementation works.</div><br><blockquote type="cite"><div><div dir="ltr"><div class="gmail_quote"><div><br></div><div>The point is that in custom VT based implementation the JVM cannot know this, because a code will have to terminate the generator loop first, while the JVM doesn't have to (similarly as done in Kotlin, if I'm not mistaken). Potentially delaying the cleanup of some VT related resources is not that big of a deal. Delaying the unreachability of the generator might be.</div><div> </div></div></div></div></blockquote><div><br></div><div>Yes it can - and it does! That is how GC languages work. Even if the JVM supported generators directly - it is still going to rely on GC for cleaning up memory resources - and a generator could use try-with-resource to clean-up other resources more quickly. Which is exactly what the implementation I shared does (the producer can use try-with-resource if it needed too).</div><div><br></div><div>Yes, there is a potential delay in when the system determines that the iterator/continuation/producer/generator is unreachable - but that is no different than any memory resource in Java. If you wanted to add a ‘close’ method to the iterator you could - for more immediate clean-up but it is not necessary. If you use the weak-reference queue you will also typically be notified far sooner than the finalizer method I used (since the finalizer needs to be scheduled and competes with other objects needing finalization).</div><br><blockquote type="cite"><div><div dir="ltr"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="auto"><div dir="ltr"><br></div><div dir="ltr">You understanding of how OOM and GC works is not correct. </div></div></blockquote><div><br></div><div>Can you clarify what exactly you are referring to? My claim is that, if the generator retains a large object (like a large array), then in a VM based implementation the JVM can see that the generator is unreachable, if the iterator is unreachable. Thus, in case it needs a lot of memory, it can conclude that there is no need for OOM. In a custom VT bsed case, there is no such chance, because it can't possibly know that the generator will soon be unreachable.</div></div></div></div></blockquote><div><br></div><div>It will know the generator is unreachable the same way it determines that any object is unreachable. If the JVM is unable to allocate memory (eg. capped) it will run full GC cycles to free memory before it triggers an OOM. If the generator (holding the memory) is still reachable then it would be in a JVM specific implementation as well - meaning the memory could not be released.</div><br><blockquote type="cite"><div><div dir="ltr"><div class="gmail_quote"><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="auto"><div dir="ltr"><br></div><div dir="ltr">My implementation does not require a queue (unless you consider a handoff variable a queue) or exceptions. </div><div dir="ltr"><br></div></div></blockquote><div><br></div><div>Yes, I'm referring to that. You yourself called that a "hand-off queue" as well. It doesn't matter how you implement it, it is still a queue.</div></div></div></div></blockquote><div><br></div><div>It is doubtful that a jvm native implementation would not use a hand-off mechanism - otherwise the generator would need to be 100% synchronous with zero read ahead - no one would want generators to work that way - it is far far less efficient than a hand-off or full queue.</div><br><blockquote type="cite"><div><div dir="ltr"><div class="gmail_quote"><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="auto"><div dir="ltr"></div><div dir="ltr">I think you’ll find the implementation I shared to be very efficient - and it was a super quick effort. An atomic CAS and LockSupport would make it even more so - but any complex generator will dominate the performance over the handoff infrastructure. </div><div dir="ltr"></div><blockquote type="cite"><div dir="ltr"><br></div></blockquote></div></blockquote><div><br></div><div>It is very efficient given your possibilities, but the JVM could do better, because it doesn't need a queue. In fact, it can just immediately change the context on the same carrier thread in `Iterator.next`, and doesn't even need to involve the queue for VT (let alone the extra queue a custom implementation needs atop of that).</div></div></div></div></blockquote><div><br></div><div>See above. It is doubtful it wouldn’t use a queue as this would be slower and not using the power/performance of concurrency. The queue size is negligible compared with the other resources probably used by a complex generator.</div><br><blockquote type="cite"><div><div dir="ltr"><div class="gmail_quote"><div><br></div><div>As for the "super quick effort". Maybe, but your implementation is far from complete, as there are a lot of additional things to deal with in the general case (when you are not just inlining a simple counting loop), obviously needs some cleanup, and also any implementation that is used in serious code would require extensive testing. All of those are non-trivial effort, and there is a lot of chance for bugs, and there would be no point in forcing many-many people to go through that, when the JDK could just provide a good and efficient implementation.</div></div></div>
</div></blockquote><br></div><div>The implementation is 100% complete, but to make it more obvious I created a new branch. <a href="https://github.com/robaho/generators/tree/complex" target="_blank">https://github.com/robaho/generators/tree/complex</a></div><div><br></div><div>That has arbitrary generators and improves the synchronization.</div><div><br></div><div>It can generate and consume 1M values in < 350 ms or 350 nanos per operation.</div><div><br></div><div>As I said, the overhead in the framework is negligible. The generators themselves if they have any complexity or IO are going to dominate the performance.</div><div><br></div><div><br></div></div></blockquote></div>
</div></blockquote></div></blockquote></div></blockquote></div></div>
</div></blockquote></body></html>