2

I'm using QLibrary to load functions from one .dll file. I succesfully load it, succesfully resolve functions. But when i use some function from that .dll for the first time, this function works very slow(even if it is very simple one). Next time i use it again - and the speed is just fine (immediately, as it should be).

What is the reason for such behaviour? I suspect some caсhing somewhere.

Edit 1: Code:

typedef int(*my_type)(char *t_id);
QLibrary my_lib("Path_to_lib.dll");
my_lib.load();
if(my_lib.isLoaded){
  my_type func = (my_type)my_lib.resolve("_func_from_dll");
  if(func){
    char buf[50] = {0};
    char buf2[50] = {0};
    //Next line works slow
    qint32 resultSlow = func(buf);
    //Next line works fast
    qint32 resultFast = func(buf2);
  }
}
Ivan
  • 43
  • 4
  • `cashing` should be `caching` – Dan M. Sep 03 '18 at 13:22
  • What does **very slow** mean? Hours? – user1810087 Sep 03 '18 at 13:25
  • @user1810087 no, about 10 seconds. But in my case it has to be milliseconds. – Ivan Sep 03 '18 at 13:31
  • Did you time each separate call ? It might be any line before the first `func(buf)` that slows down the program, which is more likely than a function being slow only one – Elcan Sep 03 '18 at 13:43
  • @FlorentUguet to be honest i simplified my code here. In real project i load dll in class constructor and then call function every time i press button. First time it is alwas slow. And yes, i'm sure - the problem is in that line. I debugged and time-debugged it. – Ivan Sep 03 '18 at 13:49
  • Try to load a library with `ResolveAllSymbolsHint` flag – Dmitry Sazonov Sep 03 '18 at 14:03
  • if you are on linux, try to use gcov/gprof to get measurement were the timewaste actually happens. – user1810087 Sep 03 '18 at 14:03
  • @DmitrySazonov same result – Ivan Sep 03 '18 at 14:15
  • You checked it under debugger? Try without. – Dmitry Sazonov Sep 03 '18 at 14:19
  • try to put debug outputs right before and after the long function call with timestamps to ensure it's that function that is taking long. It's also possible that this is the normal behaviour for that function, in case you did not create it yourself. try what happens when you link it on compile time instead of dynamic loading – Felix Sep 04 '18 at 16:02
  • I came across this question because I was using QLibrary and the functions seemed to get slower on subsequent calls. Weird if it is related to QLibrary. – karamazovbros Jun 06 '19 at 00:19

1 Answers1

0

I wouldn't blame QLibrary: func simply takes long the first time it's invoked. I bet that you'll have identical results if you resolve its address using platform-specific code, e.g. dlopen and dlsym on Linux. QLibrary doesn't really do much besides wrapping the platform API. There's nothing specific to it that would make the first call slow.

There is some code smell of doing file I/O in constructors of presumably generic classes: do the users of the class know that the constructor may block on disk I/O and thus ideally shouldn't be invoked from the GUI thread? Qt makes the doing this task asynchronously fairly easy, so I'd at least try to be nice that way:

class MyClass {
  QLibrary m_lib;
  enum { my_func = 0, other_func = 1 };
  QFuture<QVector<FunctionPointer>> m_functions;
  my_type my_func() {
    static my_type value;
    if (Q_UNLIKELY(!value) && m_functions.size() > my_func)
      value = reinterpret_cast<my_type>(m_functions.result().at(my_func));
    return value;
  }
public:
  MyClass() {
    m_lib.setFileName("Path_to_lib.dll");
    m_functions = QtConcurrent::run{
      m_lib.load();
      if (m_lib.isLoaded()) {
        QVector<QFunctionPointer> funs;
        funs.push_back(m_lib.resolve("_func_from_dll"));
        funs.push_back(m_lib.resolve("_func2_from_dll"));
        return funs;
      }
      return QVector<QFunctionPointer>();
    }
  }
  void use() {
    if (my_func()) {
      char buf1[50] = {0}, buf2[50] = {0};
      QElapsedTimer timer;
      timer.start();
      auto result1 = my_func()(buf1);
      qDebug() << "first call took" << timer.restart() << "ms";
      auto result2 = my_func()(buf2);
      qDebug() << "second call took" << timer.elapsed() << "ms";
    }
  }
};
Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313