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

Implement suspend flags as atomic variable #2361

Merged
merged 1 commit into from
Jul 21, 2023

Conversation

loganek
Copy link
Collaborator

@loganek loganek commented Jul 14, 2023

We have observed a significant performance degradation after merging #1991 Instead of protecting suspend flags with a mutex, we implement the flags as atomic variable and only use mutex when atomics are not available on a given platform.

@loganek loganek force-pushed the main branch 24 times, most recently from dba41b7 to fe64376 Compare July 17, 2023 14:31
@loganek
Copy link
Collaborator Author

loganek commented Jul 17, 2023

@wenyongh the build is passing now and the PR is ready for review. I'd appreciate your team's review. Many thanks

@@ -0,0 +1,79 @@
/*
* Copyright (C) 2023 Amazon Inc. All rights reserved.
Copy link
Collaborator

Choose a reason for hiding this comment

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

  • most of the logic in this file seems not specific to suspend flags. how about using a bit more generic name?
  • i guess the default implementation should be c11 atomics.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes, initially I've had an implementation based on stdatomics, but there are two problems with that:

  • The size of the atomic variable is not guaranteed to be the size of the base type - and this is a requirement for JIT. We could potentially workaround it with set of ifs on code generation phase though
  • this file is included (indirectly) by some c++ files (fast jit) and removing the dependency would require major refactoring. C11 stdatomics are not available in c++.

For those reasons I decided to go for a simple solution for now, but happy to iterate on that.

Copy link
Collaborator

Choose a reason for hiding this comment

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

how about "most of the logic in this file seems not specific to suspend flags. how about using a bit more generic name?"

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The file right now includes the following:

  • definitions of the suspend flag values (WASM_SUSPEND_FLAG_* definitions)
  • WASMSuspendFlags data structure
  • macros for operating on the suspend flag data structure (WASM_SUSPEND_FLAGS_* macros)
  • information whether the suspend flag is atomic (WASM_SUSPEND_FLAGS_IS_ATOMIC definition)
  • macros for locking the flag if it's not atomic (WASM_SUSPEND_FLAGS_(UN)LOCK macros)

They all seem pretty related to suspend flags.

Copy link
Collaborator

Choose a reason for hiding this comment

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

availability check and wrappers on atomic builtins are generic.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Copy link
Contributor

@nchamzn nchamzn left a comment

Choose a reason for hiding this comment

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

Have profiled this change and performance is now comparable to before the locks were added.

& WASM_SUSPEND_FLAG_SUSPEND) { \
/* suspend current thread */ \
SUSPENSION_LOCK() \
os_cond_wait(&exec_env->wait_cond, &exec_env->wait_lock); \
Copy link
Collaborator

Choose a reason for hiding this comment

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

check WASM_SUSPEND_FLAG_SUSPEND with the lock held.
otherwise wasm_cluster_resume_thread can fail to wake up the thread.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

not updating it for now as per @wenyongh 's comment

@@ -1214,7 +1219,8 @@ wasm_cluster_suspend_all_except_self(WASMCluster *cluster,
void
wasm_cluster_resume_thread(WASMExecEnv *exec_env)
{
exec_env->suspend_flags.flags &= ~0x02;
WASM_SUSPEND_FLAGS_FETCH_AND(exec_env->suspend_flags,
~WASM_SUSPEND_FLAG_SUSPEND);
os_cond_signal(&exec_env->wait_cond);
Copy link
Collaborator

Choose a reason for hiding this comment

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

forgot to take wait_lock? (not a fault of this PR though)

Copy link
Contributor

Choose a reason for hiding this comment

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

The suspend/resume APIs (wasm_cluster_suspend_xxx and wasm_cluster_resume_xxx) are not called currently, and the current implementation is incomplete, I think let's ignore it here. It is a little complex to implement a full suspend/resume mechanism, we are trying to enable it, see #2320.

#define _WASM_SUSPEND_FLAGS_H

#include "bh_platform.h"
#include "gnuc.h"
Copy link
Contributor

Choose a reason for hiding this comment

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

Could you include "gnuc.h" in "bh_platform.h" instead? We often only include "bh_platfrom.h" to include all the required APIs in core/shared/platform and core/shared/utils.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

done

#if WASM_SUSPEND_FLAGS_IS_ATOMIC != 0
#define WASM_SUSPEND_FLAGS_LOCK(lock) \
do { \
} while (0)
Copy link
Contributor

Choose a reason for hiding this comment

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

How about (void)0?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

done

@@ -1214,7 +1219,8 @@ wasm_cluster_suspend_all_except_self(WASMCluster *cluster,
void
wasm_cluster_resume_thread(WASMExecEnv *exec_env)
{
exec_env->suspend_flags.flags &= ~0x02;
WASM_SUSPEND_FLAGS_FETCH_AND(exec_env->suspend_flags,
~WASM_SUSPEND_FLAG_SUSPEND);
os_cond_signal(&exec_env->wait_cond);
Copy link
Contributor

Choose a reason for hiding this comment

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

The suspend/resume APIs (wasm_cluster_suspend_xxx and wasm_cluster_resume_xxx) are not called currently, and the current implementation is incomplete, I think let's ignore it here. It is a little complex to implement a full suspend/resume mechanism, we are trying to enable it, see #2320.

@@ -1344,7 +1350,7 @@ wasm_cluster_is_thread_terminated(WASMExecEnv *exec_env)
{
os_mutex_lock(&exec_env->wait_lock);
bool is_thread_terminated =
(exec_env->suspend_flags.flags & 0x01) ? true : false;
(WASM_SUSPEND_FLAGS_GET(exec_env->suspend_flags) & 0x01) ? true : false;
Copy link
Contributor

@wenyongh wenyongh Jul 19, 2023

Choose a reason for hiding this comment

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

Had better change 0x01 to WASM_SUSPEND_FLAG_TERMINATE

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

done

We have observed a significant performance degradation after merging
bytecodealliance#1991
Instead of protecting suspend flags with a mutex, we implement the flags
as atomic variable and only use mutex when atomics are not available
on a given platform.
@wenyongh wenyongh merged commit 0f4edf9 into bytecodealliance:main Jul 21, 2023
victoryang00 pushed a commit to victoryang00/wamr-aot-gc-checkpoint-restore that referenced this pull request May 27, 2024
We have observed a significant performance degradation after merging
bytecodealliance#1991
Instead of protecting suspend flags with a mutex, we implement the flags
as atomic variable and only use mutex when atomics are not available
on a given platform.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants