-
-
Notifications
You must be signed in to change notification settings - Fork 58
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
Shared FilePool #1236
Shared FilePool #1236
Conversation
I added a stress test and it crashes. |
@paulfd The running action hangs! Please stop it. |
I thought it stopped by itself, not running for more than one hour... I canceled it. |
1bdd023
to
5966079
Compare
Should be stopped! |
I'm sorry. but the tests finish normally when they run locally on ubuntu 22.04. |
I can revert abseil up to some version. I think I needed some form of the variant, I can double check. Do you know why it hangs with the newer abseil? |
Sorry but I don't understand why you care about Actions, it's a way for us to test the builds, if they hangs it's an Actions issue IMO, not yours for sure, they should timeout but for some reason they don't? |
the default timeout is 6 hours. hangs is my miss, I think. I will change std::condition_variable::wait() to std::condition_variable::wait_for(). Anyway with the newer Abseil-cpp, the develop branch tests fails in my environment. |
I can set timeout by writing build.yml. next time I will set it to 20 minutes. |
@redtide the time is for fee. in the free plan it is limited to 2000 minutes as I know. |
I see, thank you, so we must limit that but I'm not sure which timing is best, with macOS step in particular I'm not sure 20 could be OK, it should I guess. TBH I wasn't much aware about setting limits in the workflow file |
the actual limit is 3000 minutes per month. |
I think we should see the average and set the appropriate one, I see it's per job, so some are quick, other not |
Looking at the process that takes longer (macOS, max 6 minutes) would be OK to set them all to 10 and later maybe we can fine tune each? |
10 minutes as default, 15 for macOS and Windows, 2 for source code package
@KKQ-KKQ do you mind to try to update the abseil submodule to abseil/abseil-cpp@4a2c633 and see if it is good, so in which case we can update instead roll back to 20230125.3? EDIT: I see now that Paul needed some newer version for new code, so IIUC roll back couldn't even be possible, so maybe updating might fix the issue? BTW some time ago I added manual workflows, so in future, if you want to test your fork before submit a PR you should be able to do it. If not then we have a problem and I need to set it so people can enable actions on their side without the need to submit the PR first. |
This PR is too buggy! For better performance, the number of loading thread is 1. |
I think it becomes more stable. Please check this PR. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's a lot of work here, thanks a lot. Sadly I think I need to find more than an hour here and there to fully sit down and look at all this. I put some random comments but nothing really deep, sorry.
One thing: is it OK if I separate the seek
part of the audiofile library? It's not much but it'll help this PR to be more focused.
std::vector<FileId> lastUsedFiles; | ||
std::vector<FileAudioBuffer> garbageToCollect; | ||
public: | ||
struct GlobalObject |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not the biggest fan of this name, it feel a bit vague. I guess that this is somehow an extension of the "global threadpool" which includes both the threadpool and the filepool, but maybe we can find another more precise name (or even just change the name of the per-instance "filepools" to something else).
As I'm reading more I might have other ideas :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree. but I am not good at English. Could you suggest one or more?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will look at the rest. My intuition is that "Filepool" can actually be the Global Object and that we have other names for the filepool reference in each synth.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see. we don't have to change the names, in my opinion.
a FilePool object belongs to a Synth object (resources), FilePool::GlobalObject is a singleton object.
std::thread t1([&p] { p.wait(); }); | ||
std::thread t2([&p] { p.prepare(); }); | ||
t1.join(); | ||
t2.join(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where these the reasons for hanging tests? We could also time out on a condition variable shared by the threads. It's a bit more verbose though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added this for my local tests. I agree for that time out should be implemented.
CHECK(synth3->getNumPreloadedSamples() == 0); | ||
CHECK(filePoolGlobalObj->getNumLoadedSamples() == 1); | ||
|
||
synth1->loadSfzFile(""); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this supposed to be here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Locally the line 107 was failed before because of too much release.
They should be "Shared File Pool" and "Sliced Loading Job" when we separate this PR. |
std::mutex preloadedFilesMutex; | ||
|
||
// Preloaded data | ||
absl::flat_hash_map<FileId, std::shared_ptr<FileData>> preloadedFiles; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey, just a quick question: what made you change these to shared pointers? My concern is that this shared pointer is copied in getFilePromise
, and this copy will most probably take a locking mutex, which I want to avoid on the realtime thread.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
getFilePromise
doesn't lock any mutex
In my PR, FilePool's preloadedFiles is synchronized GlobalObject's one.
std::shared_ptr itself doesn't use mutex because it is not thread-safe when written.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI, the performance is much improved when I just changed FileData to std::shared_ptr<FileData>.
if (seekable) | ||
reader.seek(inputFrameCounter); | ||
|
||
int chunkCounter = (freeWheeling || !seekable) ? INT_MAX : static_cast<int>(sfz::config::numChunkForLoadingAtOnce); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So this chunking allows for a better scheduling of loading multiple files at once right? Forcing a round robin.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes.
I describe this PR. I'm sorry for late. Shared File Pool:In FilePool::preloadFiles(), FilePool::loadFiles(), FilePool::loadFromRam():Load data from GlobalObject::(pre)loadedFiles when the GlobalObject::(pre)loadedFiles contains the FileId. Sliced Loading Job:Added status:FileData::Status::PendingStreaming In streamFromFile():It returns false when the size of the loading reaches a certain size. In FilePool::loadingJob():Only execute when the FileData::status is PendingStreaming. Avoid from loading when the data is full-loadedAdded status:FileData::Status::FullLoaded In FilePool::preloadFiles(), FilePool::loadFiles(), FilePool::loadFromRam():Set its status to FullLoaded when full-loaded. In FilePool::getFilePromise():It queue the job only when the status is not FullLoaded. |
Thanks! So if that's OK, I will split this work into these separate components so we can integrate and work on them one by one. |
This was regarding my comment above? I'm still concerned about this but I do understand the underlying need. Let's pick up this discussion on the split pull request. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am very new to github, so many comments were "pending".
CHECK(synth3->getNumPreloadedSamples() == 0); | ||
CHECK(filePoolGlobalObj->getNumLoadedSamples() == 1); | ||
|
||
synth1->loadSfzFile(""); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Locally the line 107 was failed before because of too much release.
std::mutex preloadedFilesMutex; | ||
|
||
// Preloaded data | ||
absl::flat_hash_map<FileId, std::shared_ptr<FileData>> preloadedFiles; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
getFilePromise
doesn't lock any mutex
In my PR, FilePool's preloadedFiles is synchronized GlobalObject's one.
std::shared_ptr itself doesn't use mutex because it is not thread-safe when written.
std::vector<FileId> lastUsedFiles; | ||
std::vector<FileAudioBuffer> garbageToCollect; | ||
public: | ||
struct GlobalObject |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see. we don't have to change the names, in my opinion.
a FilePool object belongs to a Synth object (resources), FilePool::GlobalObject is a singleton object.
std::mutex preloadedFilesMutex; | ||
|
||
// Preloaded data | ||
absl::flat_hash_map<FileId, std::shared_ptr<FileData>> preloadedFiles; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI, the performance is much improved when I just changed FileData to std::shared_ptr<FileData>.
if (seekable) | ||
reader.seek(inputFrameCounter); | ||
|
||
int chunkCounter = (freeWheeling || !seekable) ? INT_MAX : static_cast<int>(sfz::config::numChunkForLoadingAtOnce); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I made a mistake in resolving. Sorry about that.
I have divided this PR into 4 PRs. |
In iOS/iPadOS, an AU plugin's process is shared.
In order to reduce its memory, I made this changes.
I fixed some issues but I cannot reopen the PR because I squashed commits.