Summary: | filenamesearch is very slow | ||
---|---|---|---|
Product: | [Frameworks and Libraries] kio-extras | Reporter: | Mark <markg85> |
Component: | default | Assignee: | Plasma Bugs List <plasma-bugs-null> |
Status: | CONFIRMED --- | ||
Severity: | normal | CC: | faure, kde, nate, postix |
Priority: | NOR | ||
Version First Reported In: | unspecified | ||
Target Milestone: | --- | ||
Platform: | Other | ||
OS: | Linux | ||
Latest Commit: | Version Fixed In: | ||
Sentry Crash Report: |
Description
Mark
2019-08-25 19:07:01 UTC
> You will get the entry as soon as there is a new match (triggering the 300ms interval) or till finished() is called.
That is also an issue if you enter a folder with a slow mount inside. KIO goes like:
while ((ep = QT_READDIR(dp)) != nullptr)
QT_LSTAT
...
listEntry(entry)
So should lstat get stuck on a slow mount, none of the previous queued up files are emitted until lstat returns and the event loop continues to then find that the 300ms batch time has expired and send all entries along, i.e. enter a folder with 30 files where there is one folder pointing to a slow mount. You won't see any files until that slow mount has responded.
Obvious solution: listEntries handling in a thread in SlaveBase :P
(In reply to Kai Uwe Broulik from comment #1) > Obvious solution: listEntries handling in a thread in SlaveBase :P Exactly my thought! And i actually have a threaded version - somewhat - working here locally, but that on it's own has some issues. - SlaveBase doesn't inherit from QObject - Due to above: no signals/slots directly I can still work around that. Just make a QThread in which a QTimer lives that does the 300ms interval. Something like: QThread *timerThread = new QThread(nullptr); // no No slavebase as parent, no QObject QTimer *timer = new QTimer(nullptr); timer->moveToThread(timerThread); That very timer should be started when the listEntry objects start flowing in and stopped when finished() is called. And that's where i am right now with another issue. In the approach from above the QTimer lives in another thread context. Aka, you cannot call _any_ functions on it from within SlaveBase. No start, stop, isActive, ... I am, right now, managing to start the timer like so: QObject::connect(timerThread, &QThread::started, [this]() { timer->start(); }); Note: the "this" is "SlaveBasePrivate", the timer and timerThread objects live in the SlaveBasePrivate scope. Do you have any idea how to start/stop a timer that lives in it's own QThread but start/stop them from within SlaveBase without signals?.... ;) You could make SlaveBasePrivate a QObject. (In reply to Kai Uwe Broulik from comment #3) > You could make SlaveBasePrivate a QObject. Hmm, i wonder if that's acceptable? Well, i can try if it works at all ;) It surely won't change ABI because it's the Private part. The only downside I can see is some overhead of QObject creation? But then, how many of those objects will we have anyway? (In reply to Kai Uwe Broulik from comment #5) > It surely won't change ABI because it's the Private part. The only downside > I can see is some overhead of QObject creation? But then, how many of those > objects will we have anyway? No it does not (without compile testing). I'd likely get into trouble with moc and signals as it's all in the cpp file. For that to work i'd have to give SlaveBasePrivate a header... #include "slavebase.moc" at the end and it should just work (In reply to Kai Uwe Broulik from comment #7) > #include "slavebase.moc" at the end and it should just work Ha, smart! Oke, so I've got that to work somewhat, but this isn't easy by far. The tricky thing is the slot connection for listEntries. They need to run on the main thread and will be executed by the main thread eventloop (via Qt::QueuedConnection). Which doesn't exist! I can call it from the thread's event loop but that makes the sockets _really_ mad and makes the slave crash, hehe :) Just handling the event in SlaveBase::dispatchLoop also isn't possible because, well, the main thread were that lives is blocked by the slave. The only solution i see now is lifting out all socket handling in a separate (QThread based?) class that isn't blocking and has an eventloop. But that is waaaaaaay beyond an easy fix. If you have more ideas, please do share! |