Skip to content

Conversation

@mkopcins
Copy link
Collaborator

Description

Added singleton class GlobalThreadPool for single threadpool management so that we don't have to spawn new threads for each async function and instead we can delegate functions to the threadpool.

Also added pthreadpool and cpuinfo binaries for iOS to allow for XNNPack threadpool configuration just like on Android

Introduces a breaking change?

  • Yes
  • No

Type of change

  • Bug fix (change which fixes an issue)
  • New feature (change which adds functionality)
  • Documentation update (improves or adds clarity to existing documentation)
  • Other (chores, tests, code style improvements etc.)

Tested on

  • iOS
  • Android

Testing instructions

Screenshots

Related issues

Checklist

  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • I have updated the documentation accordingly
  • My changes generate no new warnings

Additional notes

@mkopcins mkopcins force-pushed the @mkopcins/global-thread-pool branch 4 times, most recently from ca24036 to 18ea813 Compare September 15, 2025 11:27
@mkopcins mkopcins marked this pull request as ready for review September 15, 2025 11:28
@mkopcins mkopcins requested review from chmjkb and jakmro September 15, 2025 11:28
Comment on lines 326 to 329
WorkItem item;
item.task = std::move(task);
item.priority = priority;
item.enqueueTime = std::chrono::steady_clock::now();
Copy link
Member

@msluszniak msluszniak Sep 15, 2025

Choose a reason for hiding this comment

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

This is completely up to you, but I would probably define constructor for this struct, it's not classic POD because you have a non-copyable std::unique_ptr here. What are the benefits? More concise initialization, priority and enqueueTime might be marked private.

namespace rnexecutorch {
namespace threads {

class GlobalThreadPool {
Copy link
Contributor

Choose a reason for hiding this comment

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

Consider removing this class and leaving all functions inside the threads::global_thread_pool namespace

Copy link
Member

@msluszniak msluszniak Sep 15, 2025

Choose a reason for hiding this comment

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

HighPerformanceThreadPool should be probably implemented similarly to this one:

class Singleton {
public:
    Singleton(const Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;
    Singleton(Singleton&&) = delete;
    Singleton& operator=(Singleton&&) = delete;

    static Singleton& getInstance() {
        static std::once_flag initFlag;
        if (!instance) { 
            throw std::logic_error("Instance not initialized.");
        }
        return *instance;
    }

    static void initialize(int arg) {
        static std::once_flag initFlag;
        std::call_once(initFlag, [arg]() {
            instance = std::make_unique<Singleton>(arg);
        });
    }

private:
    int value;
    Singleton(int val) : value(val) {}

    static std::unique_ptr<Singleton> instance;
};

std::unique_ptr<Singleton> Singleton::instance = nullptr;

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I think you meant GlobalThreadPool, right? HighPerformanceThreadPool was never supposed to be a singleton

Copy link
Member

@msluszniak msluszniak Sep 16, 2025

Choose a reason for hiding this comment

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

Currently, HighPerformanceThreadPool is used only in the context of GlobalThreadPool. I guess Jakub meant that GlobalThreadPool is only a wrapper on a class that might be a singleton itself. If in the future there might be any other way to use HighPerformanceThreadPool the current design will make more sense to me then.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

That was my idea when creating this, HighPerformanceThreadPool is not meant to be a singleton, but GlobalThreadPool is. Also semantically it makes more sense to me to keep GlobalThreadPool as a class instead of a namespace even though it doesn't have any nonstatic members.

@msluszniak
Copy link
Member

Add conditional closing of this issue: #565 in the PR

Copy link
Member

@msluszniak msluszniak left a comment

Choose a reason for hiding this comment

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

Very small NITs

Copy link
Member

@msluszniak msluszniak left a comment

Choose a reason for hiding this comment

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

🚀


void setCPUAffinity() {
// AFAIK it is not possible on iOS
#ifdef __ANDROID__
Copy link
Member

Choose a reason for hiding this comment

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

You should wrap the whole function implementation with #ifdef __ANDROID__ to not introduce overhead of translating empty function body on iOS. Check other applicable places

Comment on lines +307 to +318
void setThreadPriority() {
// pthread_setschedparam doesn't work on android because permissions reasons
// and in general does not provide visible improvements on iOS

// Set nice value as fallback or additional priority boost
constexpr int nice_value = 0;
if (setpriority(PRIO_PROCESS, 0, nice_value) != 0) {
log(LOG_LEVEL::Debug, "Failed to set nice value");
} else {
log(LOG_LEVEL::Debug, "Set nice value", nice_value);
}
}
Copy link
Member

Choose a reason for hiding this comment

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

Some functions like here or getCurrentThreadId might be marked static or moved outside of the class

Copy link
Contributor

@chmjkb chmjkb left a comment

Choose a reason for hiding this comment

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

besides the single comment lgtm

Comment on lines 76 to 77
'"$(PODS_TARGET_SRCROOT)/third-party/executorch/backends/xnnpack/third-party/pthreadpool/include" '+
'"$(PODS_TARGET_SRCROOT)/third-party/executorch/backends/xnnpack/third-party/cpuinfo/include" ',
Copy link
Contributor

Choose a reason for hiding this comment

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

Shouldn't this be third-party/include/executorch/...? If this is the case then it is already included in the line above

@mkopcins mkopcins force-pushed the @mkopcins/global-thread-pool branch from 159141f to 6912d47 Compare September 23, 2025 11:24
@mkopcins mkopcins force-pushed the @mkopcins/global-thread-pool branch from 6912d47 to 5d4e588 Compare September 24, 2025 08:28
@mkopcins mkopcins merged commit 363e335 into main Sep 24, 2025
2 checks passed
@mkopcins mkopcins deleted the @mkopcins/global-thread-pool branch September 24, 2025 08:36
a-szymanska pushed a commit that referenced this pull request Sep 25, 2025
## Description

Added singleton class GlobalThreadPool for single threadpool management
so that we don't have to spawn new threads for each async function and
instead we can delegate functions to the threadpool.

Also added pthreadpool and cpuinfo binaries for iOS to allow for XNNPack
threadpool configuration just like on Android

### Introduces a breaking change?

- [ ] Yes
- [x] No

### Type of change

- [ ] Bug fix (change which fixes an issue)
- [x] New feature (change which adds functionality)
- [ ] Documentation update (improves or adds clarity to existing
documentation)
- [ ] Other (chores, tests, code style improvements etc.)

### Tested on

- [x] iOS
- [x] Android

### Testing instructions

<!-- Provide step-by-step instructions on how to test your changes.
Include setup details if necessary. -->

### Screenshots

<!-- Add screenshots here, if applicable -->

### Related issues

<!-- Link related issues here using #issue-number -->

### Checklist

- [ ] I have performed a self-review of my code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have updated the documentation accordingly
- [ ] My changes generate no new warnings

### Additional notes

<!-- Include any additional information, assumptions, or context that
reviewers might need to understand this PR. -->

---------

Co-authored-by: Mateusz Kopciński <mateusz.kopcinski@swmansnion.com>
NorbertKlockiewicz pushed a commit that referenced this pull request Oct 1, 2025
Added singleton class GlobalThreadPool for single threadpool management
so that we don't have to spawn new threads for each async function and
instead we can delegate functions to the threadpool.

Also added pthreadpool and cpuinfo binaries for iOS to allow for XNNPack
threadpool configuration just like on Android

- [ ] Yes
- [x] No

- [ ] Bug fix (change which fixes an issue)
- [x] New feature (change which adds functionality)
- [ ] Documentation update (improves or adds clarity to existing
documentation)
- [ ] Other (chores, tests, code style improvements etc.)

- [x] iOS
- [x] Android

<!-- Provide step-by-step instructions on how to test your changes.
Include setup details if necessary. -->

<!-- Add screenshots here, if applicable -->

<!-- Link related issues here using #issue-number -->

- [ ] I have performed a self-review of my code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have updated the documentation accordingly
- [ ] My changes generate no new warnings

<!-- Include any additional information, assumptions, or context that
reviewers might need to understand this PR. -->

---------

Co-authored-by: Mateusz Kopciński <mateusz.kopcinski@swmansnion.com>
KnextKoder pushed a commit to Synkhiv/react-native-executorch that referenced this pull request Nov 7, 2025
…ion#603)

## Description

Added singleton class GlobalThreadPool for single threadpool management
so that we don't have to spawn new threads for each async function and
instead we can delegate functions to the threadpool.

Also added pthreadpool and cpuinfo binaries for iOS to allow for XNNPack
threadpool configuration just like on Android

### Introduces a breaking change?

- [ ] Yes
- [x] No

### Type of change

- [ ] Bug fix (change which fixes an issue)
- [x] New feature (change which adds functionality)
- [ ] Documentation update (improves or adds clarity to existing
documentation)
- [ ] Other (chores, tests, code style improvements etc.)

### Tested on

- [x] iOS
- [x] Android

### Testing instructions

<!-- Provide step-by-step instructions on how to test your changes.
Include setup details if necessary. -->

### Screenshots

<!-- Add screenshots here, if applicable -->

### Related issues

<!-- Link related issues here using #issue-number -->

### Checklist

- [ ] I have performed a self-review of my code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have updated the documentation accordingly
- [ ] My changes generate no new warnings

### Additional notes

<!-- Include any additional information, assumptions, or context that
reviewers might need to understand this PR. -->

---------

Co-authored-by: Mateusz Kopciński <mateusz.kopcinski@swmansnion.com>
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.

5 participants