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

memory leak? #4

Open
ebiancarelli opened this issue Mar 31, 2015 · 7 comments
Open

memory leak? #4

ebiancarelli opened this issue Mar 31, 2015 · 7 comments

Comments

@ebiancarelli
Copy link

Is anyone else experience high memory usage and leaks when exercising this code?

I'm using qt5.2.1 and this code in conjunction with a sample python selenium script that loads Yahoo and does a search. If I run this test code a few times, I can see the allocated memory in 'htop' is climbing and not recovering. I have an advanced test suite that can drive the browser to exhaust all available memory. :-(

@hekra01
Copy link
Contributor

hekra01 commented Mar 31, 2015

Also run Qt5.2 test suites (java/python) but have not observed such issue yet.
Could you please provide your sample script?

@ebiancarelli
Copy link
Author

I'll note that I'm running qt5.2.1 with several patches applied for performance improvements in WebKit. I'm not running stock qt5.2.1...I do have a basic WebView application that I am driving.

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities

import unittest

class SeleniumTest(unittest.TestCase):

    def setUp(self):
        print('In setUp()')
        #self.browser = webdriver.Firefox()
        #self.browser = webdriver.Remote(command_executor='http://10.143.32.80:9517',
        self.browser = webdriver.Remote(command_executor='http://192.168.0.36:9517',
                                desired_capabilities={'browserName': 'chrome', 'browserStartWindow': '*'})
        self.browser.get('http://cnn.com')

    def tearDown(self):
        print('In tearDown()')
        self.browser.quit()

    def testPageTitle(self):
        self.browser.get('http://www.google.com')
        self.assertIn('Google', self.browser.title)

        #self.browser.get('http://www.yahoo.com')
        #assert 'Yahoo' in self.browser.title
        self.browser.get('https://msb-eng.timewarnercable.com/hnavc/hnavclient-stable/?profile=dev&noHam=true&noHydra=true&oauth.forceUserNamePwd=true')
        assert 'TWC TV' in self.browser.title

        print self.browser.title
        print self.browser.current_url
        print self.browser.current_window_handle

        classes = {}

        elems = self.browser.find_elements_by_tag_name('div')
        for elem in elems:
            class_name = elem.get_attribute('class')
            if class_name in classes:
                classes[class_name] += 1
            else:
                classes[class_name] = 1

        for class_name, count in classes.iteritems():
            print class_name, count

        elem = self.browser.find_element_by_name('p')  # Find the search box
        elem.send_keys('seleniumhq' + Keys.RETURN)

        print elem.text, elem.tag_name


if __name__ == '__main__':
    unittest.main()

WebView application

#include <QGraphicsView>
#include <QGLWidget>

#include <QtDebug>
#include <QtWebKitWidgets>

#include <iostream>

void setWindowTitle(QWindow *window)
{
    QString title =
            "QT-" QT_VERSION_STR
#ifdef QT_OPENGL_ES_2
            "-EGL"
#else
            "-GLX"
#endif
#ifdef QT_NO_DEBUG
            "-RELEASE"
#else
            "-DEBUG"
#endif
            ;

    window->setTitle(title);
}

QGraphicsView *viewForItem(QGraphicsItem *item, bool openGL = true)
{
    QGraphicsView *view = new QGraphicsView;
    view->setScene(new QGraphicsScene);
    if (openGL) {
        QGLWidget *glWidget = new QGLWidget(QGLFormat(QGL::SampleBuffers));
        view->setViewport(glWidget);
    }

    view->scene()->addItem(item);
    view->resize(1282, 722);
    view->show();

    setWindowTitle(view->windowHandle());

    return view;
}

extern void startWebDriver(int argc, char **argv);

int main(int argc, char **argv)
{
    QApplication app(argc, argv);

    QWebSettings::globalSettings()->setAttribute(QWebSettings::AcceleratedCompositingEnabled, true);

#if QT_VERSION >= QT_VERSION_CHECK(5, 4, 0)
    QWebSettings::globalSettings()->setAttribute(QWebSettings::Accelerated2dCanvasEnabled, true);
#endif
    QWebSettings::globalSettings()->setAttribute(QWebSettings::DeveloperExtrasEnabled, true);
    QWebSettings::globalSettings()->setAttribute(QWebSettings::LocalStorageEnabled, true);

    int capacity = 20 * 1024 * 1024;
    QWebSettings::setObjectCacheCapacities(0, capacity, capacity);

    QWebSettings::enablePersistentStorage(QFileInfo(".").absoluteFilePath());

    QUrl url;

    if (argc > 1) {
        url = QUrl(argv[1]);
    } else {
        url = QUrl("https://msb-eng.timewarnercable.com/hnavc/hnavclient-stable/?profile=dev&noHam=true&noHydra=true&oauth.forceUserNamePwd=true");
        url.setUserName("hnav-vendor");
        url.setPassword("SUspuC%259");
    }

    qDebug() << url;

    QGraphicsWebView *web = new QGraphicsWebView;
    QWebPage *page = new QWebPage(web);
    page->mainFrame()->load(url);
    web->setPage(page);
    web->resize(1280, 720);

    web->setFocusPolicy(Qt::StrongFocus);

    viewForItem(web);

    startWebDriver(argc, argv);

    return app.exec();
}

webdriver.cpp

#include "webdriver_server.h"
#include "webdriver_view_transitions.h"

#include "extension_qt/q_view_runner.h"
#include "extension_qt/q_session_lifecycle_actions.h"

#include "extension_qt/qwebviewext.h"

#include "extension_qt/web_view_creator.h"
#include "extension_qt/web_view_executor.h"
#include "extension_qt/web_view_enumerator.h"

#include "extension_qt/graphics_web_view_executor.h"
#include "extension_qt/graphics_web_view_enumerator.h"

#include <iostream>

void startWebDriver(int argc, char **argv)
{
    CommandLine commandLine(CommandLine::NO_PROGRAM);
    commandLine.InitFromArgv(argc, argv);

    webdriver::ViewRunner::RegisterCustomRunner<webdriver::QViewRunner>();

    webdriver::SessionLifeCycleActions::RegisterCustomLifeCycleActions<webdriver::QSessionLifeCycleActions>();

    //webdriver::ViewEnumerator::AddViewEnumeratorImpl(new webdriver::WebViewEnumeratorImpl());
    //webdriver::ViewCmdExecutorFactory::GetInstance()->AddViewCmdExecutorCreator(new webdriver::QWebViewCmdExecutorCreator());

    webdriver::ViewEnumerator::AddViewEnumeratorImpl(new webdriver::GraphicsWebViewEnumeratorImpl());
    webdriver::ViewCmdExecutorFactory::GetInstance()->AddViewCmdExecutorCreator(new webdriver::GraphicsWebViewCmdExecutorCreator());

    webdriver::Server* server = webdriver::Server::GetInstance();
    int configureError = server->Configure(commandLine);
    if (configureError) {
        std::cout << "Error while configuring webdriver server, errorCode " << configureError << std::endl;
        return;
    }

    int startError = server->Start();
    if (startError) {
        std::cout << "Error while starting webdriver server, errorCode " << startError << std::endl;
        return;
    }
}

webview.pro

######################################################################
# Automatically generated by qmake (3.0) søn. okt. 26 15:04:50 2014
######################################################################

TEMPLATE = app
TARGET = webview
INCLUDEPATH += .

QT += widgets opengl webkitwidgets

# Input
SOURCES += main.cpp

@hekra01
Copy link
Contributor

hekra01 commented Apr 7, 2015

Hi

WebDriver should be started in Qt main loop
I suggest you start the WebDriver in the same thread as you app

int main(int argc, char **argv) {
    // etc...

    // Start WebDriver
    int startError = wd_server->Start();
    if (startError){
        std::cout << "Error while starting server, errorCode " << startError << std::endl;
        return startError;
    }

    QGraphicsWebView *web = new QGraphicsWebView;
    QWebPage *page = new QWebPage(web);
    // etc....

    return app.exec();

An example test app is available here https://github.com/cisco-open-source/qtwebdriver/blob/WD_1.X_dev/src/Test/main.cc

@ebiancarelli
Copy link
Author

I updated my previous comment and included the code we use to start the web driver. We do start it from the main thread (sorry, I added that in too). Maybe I need to use different options to start the server and in my 'capabilities' set in the test?

@hekra01
Copy link
Contributor

hekra01 commented Apr 8, 2015

Python test is fine.

  • used your test and app code
  • build without opengl support: No leak observed
    Looks like the leak is caused by this or due to opengl
    if (openGL) {
        QGLWidget *glWidget = new QGLWidget(QGLFormat(QGL::SampleBuffers));
        view->setViewport(glWidget);
    }

@ebiancarelli
Copy link
Author

Have tried with and without OpenGl. I can get the memory issue to happen. I've asked another developer to reproduce my findings, and he also can see the memory leak.

We've done research into why there is a memory leak, but have not made headway due to the large WebKit codebase.

@hekra01
Copy link
Contributor

hekra01 commented May 21, 2015

We reproduced the leak, even launching pages without WD.
Looking into it

isabelleknott added a commit to kobolabs/qtwebdriver that referenced this issue Oct 21, 2019
Less QEventLoops in widget executors & delay server responses until t…
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

No branches or pull requests

2 participants