До нього у мене, власне, дві претензії (якщо не рахувати купу питань щодо юзабіліті):
Сьогодні під час компіляції libreoffice (10 Gb tmpfs, 5 паралельних процесів) мені терміново треба була інформація із вчорашнього листа. Перемкнувшись на 6-й десктоп я побачив що? Правильно, сірий квадрат замість KMail. При цьому Akregator, Okular і навіть Firefox працювали без помітних тормозів. Wtf?
strace показав що KMail нічим не зайнятий, тупо висить на select. gdb показав цікаву картинку.
Почнемо знизу:
Нічого цікавого. Прилетів pain event і він почав малювати. Далі йдуть з десяток викликів QWidgetPrivate::paintSiblingsRecursive, я не буду їх наводити. Йдемо вище:
Теж нічого підозрілого, стандартний QTreeView малює себе. Йдемо далі:
Естафетна паличка художника перейшла до делегату. Питаємо, який фоновий колір ставити для мессиджа. Проблема уже тут, але її все ще не видно. Йдемо далі:
Розміру проблеми ще не видно, але волосся починає шевелитися. Набираємось сміливості, робимо кілька глибоких вдихів і йдемо до кінця:
Нагадаю: Nepomuk - система керування метаданими, Soprano - об’єктно-орієнтований інтерфейс до метаданих. Виходить що? Виходить що для того щоб визначити колір фону для ячейки треба залізти у СУБД! І так для кожної ячейки! Для кожного paint event!
Поліз у сорси.
ThemeDelegate::paint
Ось цей "дядя з великиму вухами"! Що ж він такого робить у backgroundColor()?
MessageItem::backgroundColor
MessageItemPrivate::bestTag
Ну логічно що йому потрібен список тегів.
MessageItemPrivate::getTagList
Ага! "Ліниве" створення списку. Ну а fillTagList уже лізе в Nepomuk і звідти цей список витягує. Виникає питання: чому список тегів пустий якщо це не перший пейнт?
Ех, мені б трохи зайвого часу, я б цей KMail розкрутив по гвинтикам і пофіксив ці довбані баги (благо, №277399 у мене проявляється регулярно).
PS: вони (LJ) таки полагодили попередній перегляд!
- Bug 277399 - kmail2 inbox only shows messages that were fetched since the last kmail start;
- швидкодія інтерфейсу.
Сьогодні під час компіляції libreoffice (10 Gb tmpfs, 5 паралельних процесів) мені терміново треба була інформація із вчорашнього листа. Перемкнувшись на 6-й десктоп я побачив що? Правильно, сірий квадрат замість KMail. При цьому Akregator, Okular і навіть Firefox працювали без помітних тормозів. Wtf?
strace показав що KMail нічим не зайнятий, тупо висить на select. gdb показав цікаву картинку.
Почнемо знизу:
#52 0x00007f498ff9fabc in QWidgetPrivate::paintSiblingsRecursive(QPaintDevice*, QList<QObject*> const&, int, QRegion const&, QPoint const&, int, QPainter*, QWidgetBackingStore*) () from /usr/lib64/qt4/libQtGui.so.4 #53 0x00007f498ff9ed60 in QWidgetPrivate::drawWidget(QPaintDevice*, QRegion const&, QPoint const&, int, QPainter*, QWidgetBackingStore*) () from /usr/lib64/qt4/libQtGui.so.4 #54 0x00007f4990168ad8 in QWidgetBackingStore::sync() () from /usr/lib64/qt4/libQtGui.so.4 #55 0x00007f4990168daa in QWidgetBackingStore::sync(QWidget*, QRegion const&) () from /usr/lib64/qt4/libQtGui.so.4 #56 0x00007f498ffce8b0 in QETWidget::translatePaintEvent(_XEvent const*) () from /usr/lib64/qt4/libQtGui.so.4 #57 0x00007f498ffcf64c in QApplication::x11ProcessEvent(_XEvent*) () from /usr/lib64/qt4/libQtGui.so.4 #58 0x00007f498fff68a2 in x11EventSourceDispatch(_GSource*, int (*)(void*), void*) () from /usr/lib64/qt4/libQtGui.so.4 #59 0x00007f4987ad311a in g_main_context_dispatch () from /usr/lib64/libglib-2.0.so.0 #60 0x00007f4987ad3928 in g_main_context_iterate.clone.6 () from /usr/lib64/libglib-2.0.so.0 #61 0x00007f4987ad3abf in g_main_context_iteration () from /usr/lib64/libglib-2.0.so.0 #62 0x00007f498fa71f5a in QEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () from /usr/lib64/qt4/libQtCore.so.4 #63 0x00007f498fff6566 in QGuiEventDispatcherGlib::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () from /usr/lib64/qt4/libQtGui.so.4 #64 0x00007f498fa46112 in QEventLoop::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) () from /usr/lib64/qt4/libQtCore.so.4 #65 0x00007f498fa46394 in QEventLoop::exec(QFlags<QEventLoop::ProcessEventsFlag>) () from /usr/lib64/qt4/libQtCore.so.4 #66 0x00007f498fa4a87b in QCoreApplication::exec() () from /usr/lib64/qt4/libQtCore.so.4 #67 0x00000000004031f2 in main ()
Нічого цікавого. Прилетів pain event і він почав малювати. Далі йдуть з десяток викликів QWidgetPrivate::paintSiblingsRecursive, я не буду їх наводити. Йдемо вище:
#18 0x00007f499048568a in QTreeView::drawRow(QPainter*, QStyleOptionViewItem const&, QModelIndex const&) const () from /usr/lib64/qt4/libQtGui.so.4 #19 0x00007f49904885a5 in QTreeView::drawTree(QPainter*, QRegion const&) const () from /usr/lib64/qt4/libQtGui.so.4 #20 0x00007f4990488f9f in QTreeView::paintEvent(QPaintEvent*) () from /usr/lib64/qt4/libQtGui.so.4 #21 0x00007f498ffa2135 in QWidget::event(QEvent*) () from /usr/lib64/qt4/libQtGui.so.4 #22 0x00007f49903391de in QFrame::event(QEvent*) () from /usr/lib64/qt4/libQtGui.so.4 #23 0x00007f499044572b in QAbstractItemView::viewportEvent(QEvent*) () from /usr/lib64/qt4/libQtGui.so.4 #24 0x00007f499048a244 in QTreeView::viewportEvent(QEvent*) () from /usr/lib64/qt4/libQtGui.so.4 #25 0x00007f498fa46f66 in QCoreApplicationPrivate::sendThroughObjectEventFilters(QObject*, QEvent*) () from /usr/lib64/qt4/libQtCore.so.4 #26 0x00007f498ff50093 in QApplicationPrivate::notify_helper(QObject*, QEvent*) () from /usr/lib64/qt4/libQtGui.so.4 #27 0x00007f498ff54c1a in QApplication::notify(QObject*, QEvent*) () from /usr/lib64/qt4/libQtGui.so.4 #28 0x00007f49917f1948 in KApplication::notify(QObject*, QEvent*) () from /usr/lib64/libkdeui.so.5 #29 0x00007f498fa46dcb in QCoreApplication::notifyInternal(QObject*, QEvent*) () from /usr/lib64/qt4/libQtCore.so.4
Теж нічого підозрілого, стандартний QTreeView малює себе. Йдемо далі:
#14 0x00007f498aecb2b1 in MessageList::Core::MessageItemPrivate::getTagList() const () from /usr/lib64/libmessagelist.so.4 #15 0x00007f498aecb4da in MessageList::Core::MessageItemPrivate::bestTag() const () from /usr/lib64/libmessagelist.so.4 #16 0x00007f498aecb7ad in MessageList::Core::MessageItem::backgroundColor() const () from /usr/lib64/libmessagelist.so.4 #17 0x00007f498aeef525 in MessageList::Core::ThemeDelegate::paint(QPainter*, QStyleOptionViewItem const&, QModelIndex const&) const () from /usr/lib64/libmessagelist.so.4
Естафетна паличка художника перейшла до делегату. Питаємо, який фоновий колір ставити для мессиджа. Проблема уже тут, але її все ще не видно. Йдемо далі:
#9 0x00007f49880ecb8f in Nepomuk::ResourceData::load() () from /usr/lib64/libnepomuk.so.4 #10 0x00007f49880ece9c in Nepomuk::ResourceData::property(QUrl const&) () from /usr/lib64/libnepomuk.so.4 #11 0x00007f498810054a in Nepomuk::Resource::property(QUrl const&) const () from /usr/lib64/libnepomuk.so.4 #12 0x00007f4988100e99 in Nepomuk::Resource::tags() const () from /usr/lib64/libnepomuk.so.4 #13 0x00007f498aeca9ad in MessageList::Core::MessageItemPrivate::fillTagList() const () from /usr/lib64/libmessagelist.so.4
Розміру проблеми ще не видно, але волосся починає шевелитися. Набираємось сміливості, робимо кілька глибоких вдихів і йдемо до кінця:
#0 0x00007f498f10bee3 in select () from /lib64/libc.so.6 #1 0x00007f498fa6f03a in qt_safe_select(int, fd_set*, fd_set*, fd_set*, timeval const*) () from /usr/lib64/qt4/libQtCore.so.4 #2 0x00007f498e17dfd9 in QNativeSocketEnginePrivate::nativeSelect(int, bool, bool, bool*, bool*) const () from /usr/lib64/qt4/libQtNetwork.so.4 #3 0x00007f498e166c04 in QNativeSocketEngine::waitForReadOrWrite(bool*, bool*, bool, bool, int, bool*) () from /usr/lib64/qt4/libQtNetwork.so.4 #4 0x00007f498e177fc9 in QAbstractSocket::waitForReadyRead(int) () from /usr/lib64/qt4/libQtNetwork.so.4 #5 0x00007f4981895fce in Soprano::Client::ClientConnection::executeQuery(int, QString const&, Soprano::Query::QueryLanguage, QString const&) () from /usr/lib64/libsopranoclient.so.1 #6 0x00007f49818977c5 in Soprano::Client::ClientModel::executeQuery(QString const&, Soprano::Query::QueryLanguage, QString const&) const () from /usr/lib64/libsopranoclient.so.1 #7 0x00007f49880f6bb5 in Nepomuk::MainModel::executeQuery(QString const&, Soprano::Query::QueryLanguage, QString const&) const () from /usr/lib64/libnepomuk.so.4 #8 0x00007f49883dde31 in Soprano::FilterModel::executeQuery(QString const&, Soprano::Query::QueryLanguage, QString const&) const () from /usr/lib64/libsoprano.so.4
Нагадаю: Nepomuk - система керування метаданими, Soprano - об’єктно-орієнтований інтерфейс до метаданих. Виходить що? Виходить що для того щоб визначити колір фону для ячейки треба залізти у СУБД! І так для кожної ячейки! Для кожного paint event!
Поліз у сорси.
ThemeDelegate::paint
if ( !index.isValid() )
return; // bleah
Item * item = itemFromIndex( index );
if ( !item )
return; // hm...
QStyleOptionViewItemV4 opt = option;
initStyleOption( &opt, index );
opt.text.clear(); // draw no text for me, please.. I'll do it in a while
// Set background color of control if necessary
if ( item->type() == Item::Message ) {
MessageItem * msgItem = static_cast< MessageItem * >( item );
if ( msgItem->backgroundColor().isValid() )
opt.backgroundBrush = QBrush( msgItem->backgroundColor() );
}
Ось цей "дядя з великиму вухами"! Що ж він такого робить у backgroundColor()?
MessageItem::backgroundColor
QColor MessageItem::backgroundColor() const
{
Q_D( const MessageItem );
const Tag *bestTag = d->bestTag();
if ( bestTag != 0 ) {
return bestTag->backgroundColor();
} else {
return QColor();
}
}
MessageItemPrivate::bestTag
const MessageItem::Tag* MessageItemPrivate::bestTag() const
{
const MessageItem::Tag *best = 0;
foreach( const MessageItem::Tag* tag, getTagList() ) {
if ( !best || tag->priority() < best->priority() )
best = tag;
}
return best;
}
Ну логічно що йому потрібен список тегів.
MessageItemPrivate::getTagList
QList<MessageItem::Tag*> MessageItemPrivate::getTagList() const
{
if ( !mTagList )
fillTagList();
return *mTagList;
}
Ага! "Ліниве" створення списку. Ну а fillTagList уже лізе в Nepomuk і звідти цей список витягує. Виникає питання: чому список тегів пустий якщо це не перший пейнт?
Ех, мені б трохи зайвого часу, я б цей KMail розкрутив по гвинтикам і пофіксив ці довбані баги (благо, №277399 у мене проявляється регулярно).
PS: вони (LJ) таки полагодили попередній перегляд!