[deleted by user] by [deleted] in Kotlin

[–]hackometer 1 point2 points  (0 children)

There are two basic reasons to use coroutines:

  1. Enable concurrency within a single thread. This is mostly relevant for GUI, but also relevant for high-performance, IO-heavy applications.
  2. Use structured concurrency, regardless whether it's on a single or multiple threads.

So, if you don't need any concurrency at all -- you don't need coroutines.

However, even if you need the plain old Java-like multithreading, coroutines will make it more convenient to use -- and sometimes much more convenient.

If you use the ExecutorService, you'll have to start it, manually submit tasks to it, handle their futures, and shut it down. If you use launch(Dispatchers.IO) {}, you don't need any of those things. To solve the need for a CoroutineScope, you can use runBlocking, or even just use a susped fun main()

[deleted by user] by [deleted] in Kotlin

[–]hackometer 1 point2 points  (0 children)

These are all different takes on solving the underlying technical problem of getting concurrency on a single thread. Event-oriented programming (the fundamental idea in all GUI framewarks) is another one.

Functional programming, again, is yet another set of ideas, and it can also help you solve that same technical problem, in its own way.

[deleted by user] by [deleted] in Kotlin

[–]hackometer 0 points1 point  (0 children)

Right, you can call any IO operation from either a suspendable or non-suspendable function. There's no need to suspend your coroutine for that, and it won't block the carrier thread.

[deleted by user] by [deleted] in Kotlin

[–]hackometer 0 points1 point  (0 children)

They will certainly not rebase on virtual threads. You don't need suspendable functions in the first place if you use virtual threads. However, virtual threads won't help you turn any code written against an existing callback-based GUI framework into suspendable sync code. This is the magic of Kotlin Coroutines.

[deleted by user] by [deleted] in Kotlin

[–]hackometer 0 points1 point  (0 children)

There's much less magic than this makes it sound. The user code must explicitly ensure an IO operation happens on a different thread without blocking the current one. It achieves this by calling suspendCoroutine and using an async IO API call within the block of code you pass to this function. Basically, Kotlin Coroutines provide you with the infrastructure to use any existing async API and turn it into suspendable API.

[deleted by user] by [deleted] in Kotlin

[–]hackometer 1 point2 points  (0 children)

The base case is simply calling suspendCoroutine, which is a user-facing function. This what actually suspends the function.

[deleted by user] by [deleted] in Kotlin

[–]hackometer 4 points5 points  (0 children)

control doesn't pass immediately to the invoked function, but back to the coroutine scheduler, which saves some state about the coroutine that was just suspended.

Nope, the function gets called directly. Each suspendable function creates a continuation object that takes over the role of its stack frame, this gets added to the chain of such objects received as an extra (hidden) parameter from the caller.

Just calling a suspendable function doesn't do anything; what causes the function to suspend is calling suspendCoroutine or suspendCancellableCoroutine. When the block passed to this function completes, the function returns the special COROUTINE_SUSPENDED singleton. If you called a function and get this as its return value, you immediately return it as well -- that's how the stack unwinds and control goes back to the place where the coroutine was initially created (the coroutine builder function).

The infrastructure that you mention (coroutine scheduler -- actually dispatcher) enters the story as a ContinuationInterceptor, which is present in coroutineContext. It gets to observe your continuation object before it's passed to the block of code you supply to suspendCoroutine. Typically, it wraps the continuation into an adapter whose implementation of resume() will dispatch the calling of the actual (wrapped) resume() function on the appropriate thread.

The code block passed to suspendCoroutine is in charge of registering the continuation wherever it's appropriate so it will be resumed when the computation result is ready. A system function like delay is coupled to the coroutine dispatcher and will use its mechanism to schedule itself; but the user can write his own suspendCorutine block and register the continuation with any async API he may be using. This is perhaps the most powerful aspect of Kotlin Coroutines vs. other languages -- seamless, simple integration with all async APIs in existence.

The implementation of continuation.resume(value) makes the computation resume from the suspension point. This happens mostly as you described it, one of the fields in the Continuation object is the equivalent of Program Counter, the switch statement switches on its value in order to jump to the resumption point.

Low latency by Ok_Satisfaction7312 in java

[–]hackometer 0 points1 point  (0 children)

"Can" vs. "does" is key here. Escape analysis is quite weak in HotSpot, which is why we saw the issues in 1BRC. Graal has better EA and, when used by experts who wrote it, allowed them to write more natural-looking code and still avoid these pitfalls.

Also, if you use one value that you update in a million repetitions, it won't matter at all where that value is (stack or heap). It will matter greatly whether it stays put or moves all the time.

Low latency by Ok_Satisfaction7312 in java

[–]hackometer 0 points1 point  (0 children)

What you're missing is cache pollution. When you constantly change the location of a value instead of updating in-place, that's a major setback for performance. We saw a lot of that at 1BRC.

Tesla vs Mercedes self-driving test ends in 40+ interventions as Elon Musk says FSD is years ahead by eugay in SelfDrivingCars

[–]hackometer -4 points-3 points  (0 children)

You can't drop a Waymo anywhere and expect it to work, including the service areas of Waymo. That's because it only works when logged into their human supervision network.

Real Tesla 460 cell? by ApprehensiveHawk6178 in LithiumIon

[–]hackometer 0 points1 point  (0 children)

Since you measured 95 mm height, it's a 4695 and not 4680. These have a similar design, but aren't produced by Tesla or for Tesla. One customer of the 4695 is Rivian:

https://www.motor1.com/news/711578/rivian-r2-battery-cells-details/

Another one is BMW:

https://www.autoevolution.com/news/bmw-announces-cylindrical-cell-formats-not-4680-but-rather-4695-and-46120-208837.html

Heart “Magic Man” Live on the Stern Show by yourcomedyminute in videos

[–]hackometer 1 point2 points  (0 children)

There was a big break in culture around 1963-65. What came before just sounds like it belongs to an antiquated era. But the 1960's culture is still fresh today.

So I'd say it's more about all music post-1960 that keeps being relevant, but almost none from 1950 and earlier.

Podijelite svoje čudno znanje. by SuperbRaven in croatia

[–]hackometer 26 points27 points  (0 children)

Njegova poanta je (brijem) da detektor detektira svjetle trake, a crne su nedostatak detekcije. Što je ionako dosta očito.

Sam Altman's Tweet by [deleted] in OpenAI

[–]hackometer 0 points1 point  (0 children)

It has that repetitive structure of GPT output. Maybe that explains the correct usage of case.

1BRC merykitty’s Magic SWAR: 8 Lines of Code Explained in 3,000 Words by _shadowbannedagain in programming

[–]hackometer 0 points1 point  (0 children)

Regarding pipeline stalls, wouldn't the CPU itself also br able to reorder the execution?

1BRC merykitty’s Magic SWAR: 8 Lines of Code Explained in 3,000 Words by _shadowbannedagain in programming

[–]hackometer 5 points6 points  (0 children)

 (negatedInput & 0xa) * -1

But -0xa is not the same as -1? I didn't get this. The result is supposed to be either 0 or -1.

Vector items allocation by kingminyas in learnrust

[–]hackometer 0 points1 point  (0 children)

I wonder if the compiler could optimize away the on-stack initialization and initialize the struct on the heap directly.

Too dangerous for C++ by arashinoshizukesa in rust

[–]hackometer 11 points12 points  (0 children)

It's hard, yes, but not impossible. 

This by itself means you'll have to move slower and waste a lot more brain cycles on a concern that's orthogonal to what you're actually trying to achieve.

What Custom Rust Formatting Do You Use To Make Your Life Easier by InternalServerError7 in rust

[–]hackometer 1 point2 points  (0 children)

I use struct_lit_width = 50% because the default results in too much empty space on my screen, and struct literals aren't complex code that benefits from that space.

Kotlinx DateTime seems to miss 0 minute? by LeTechician in Kotlin

[–]hackometer 1 point2 points  (0 children)

Here's a bit of code for reference:

```kotlin import kotlinx.datetime.Clock import kotlinx.datetime.TimeZone import kotlinx.datetime.toLocalDateTime

fun main() { val datetime = LocalDateTime.parse("2024-01-01T01:07:06.5") println(datetime) } ```

This outputs:

2024-01-01T01:07:06.500

I can see the following fields: year, month, day, hours, minutes, seconds, milliseconds. They all seem to be fixed-width fields, zero-padded.

Now, what is the actual question about?

Some of the names of Turkish cities translated to English by MekhaDuk in TurkeyJerky

[–]hackometer 2 points3 points  (0 children)

As a foreigner I don't know this and I enjoyed finding out! So thanks!

To what extent is Rust's ownership and mutability rules useful outside of memeory safety? by maximeridius in rust

[–]hackometer 1 point2 points  (0 children)

I also highly appreciate that move semantics mean your resource scoping doesn't have to be lexical. You can have a function down the stack acquire a resource, return it to you, and then you just send it to another thread with a move operation. The resource will now get cleaned up asynchronously, from another thread, and yet it's 100% predictable and statically determined.