Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Do not merge][Preview] This is a preview version of WasmEdge coroutine. #2715

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

hydai
Copy link
Member

@hydai hydai commented Aug 3, 2023

The API may change if there is any design decision update

…y change if there is any design decision update

Signed-off-by: hydai <z54981220@gmail.com>
Copy link
Member

juntao commented Aug 3, 2023

Hello, I am a code review bot on flows.network. Here are my reviews of code commits in this PR.


Commit 92025d386697083a09f1f273b2d7b916a253a05b

The key changes in this patch are related to the inclusion of coroutine functionality in the WasmEdge runtime. Specific modifications include:

  1. A new structure called WasmEdge_Coroutine is introduced to represent the result of a coroutine.

  2. An invocation function that uses coroutines, WasmEdge_ExecutorCoroutineInvoke(), is added. This function allows developers to run a WebAssembly function instance in a coroutine mode.

  3. Additionally, several utility functions are introduced to manage the lifecycle of a coroutine:

    • WasmEdge_CallingFrameCoroutineSuspend() is used to suspend the execution of coroutine.
    • WasmEdge_CoroutineSpawn() starts executing a coroutine.
    • WasmEdge_CoroutineResume() continues executing a suspended coroutine.
    • WasmEdge_CoroutineRelease() releases resources of a coroutine but doesn't destroy it.
    • WasmEdge_CoroutineGetReturnsLength() waits for the coroutine's execution and returns its value length.
    • WasmEdge_CoroutineGet() waits for the coroutine execution and retrieves its result.
    • WasmEdge_CoroutineDelete() destroys a coroutine.

Potential problems:

  1. The code doesn't appear to handle situations where coroutines are misused, such as attempting to resume a coroutine that hasn't been started.

  2. The patch proposes deletion methods for coroutines and indicates that they should not be used after being destroyed. However, no safeguards seem to be in place preventing destroyed coroutines from being invoked. This could result in undefined behavior and should at least be clearly documented.

  3. Coroutine handling and lifecycle can be tricky, especially around edge cases. It's crucial to validate this new system against concurrent executions, memory leaks, and unexpected behavior.

  4. As it is explicitly mentioned that this is a preview version and the API may change, it is advised to ensure proper versioning and backward compatibility when this feature gets updated or changed in the future.

@github-actions github-actions bot added the c-CAPI An issue related to the WasmEdge C API label Aug 3, 2023
///
/// \param Cxt the WasmEdge_CallingFrameContext.
WASMEDGE_CAPI_EXPORT extern void
WasmEdge_CallingFrameCoroutineSuspend(const WasmEdge_CallingFrameContext *Cxt);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How is this expected to be used? Is another thread expected to call this?

Ideally for our use case we would suspend execution periodically using gas metering

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @rockwotj
This feature is for those who want to suspend the execution from the host functions. We have some use cases that will spend much time waiting for IO. They would like to suspend the execution until the IO is ready and get it back.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. We do this today using std::longjmp to jump out from the host function then back in on a separate stack.

An important use case for our thread-per-core architecture is that one task doesn't hog the CPU for too long. Otherwise that means other requests that thread is responsible for cannot be responded, increasing tail latencies in these situations. See https://github.com/scylladb/seastar/blob/master/doc/tutorial.md#breaking-up-long-running-computations

Anyways, it seems this mechanism and set of APIs won't solve this use case and instead we need some callback function to be periodically invoked from the runtime while executing.

/// Start to execute a WasmEdge_Coroutine execution.
///
/// \param Cxt the WasmEdge_Coroutine.
WASMEDGE_CAPI_EXPORT void WasmEdge_CoroutineSpawn(WasmEdge_Coroutine *Cxt);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you going to be creating a separate stack here (or is this a stackful or stackless coroutine)? If so it's useful to add the amount of memory used here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am going to have a stackful coroutine. Would you like any other information (memory usage sounds useful)?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hard to tell without knowing a little bit more about the implementation (are you using guard pages, will stacks be segmented or contiguous?, can stacks grow or are they fixed?). But at a minimum the size of the stack is a must, as I believe "normal" threads can have up to a 2MiB stack, but in an environment like Redpanda we have very little memory and use 128KiB stacks

/// This is only available when using WasmEdge_Coroutine.
///
/// \param Cxt the WasmEdge_CallingFrameContext.
WASMEDGE_CAPI_EXPORT extern void
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps developers working on the host section need to know which module's host function triggered the suspend. Therefore, I hope that it can return a pointer to the module instance to which the triggering host function belongs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
c-CAPI An issue related to the WasmEdge C API
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants