LINUX.ORG.RU

Внутреннее устройство Qt

 , ,


0

5

Где можно почитать о внутреннем устройстве Qt, кроме исходников?

В частности, интересует описание работы Qt SQL C++ классов. Что происходит «под капотом». Как устроена работа с памятью. Где и как хранятся результаты выборки, когда и как освобождается память занятая под ними и т.п.

Также прошу дать ссылки на исходники грамотных Qt C++ проектов, в которых ведется работа с БД.

Про QtSql ничего кроме сорцов и доков читать и нечего.

Как устроена работа с памятью.

Как обычно.

Где и как хранятся результаты выборки, когда и как освобождается память занятая под ними и т.п.

QVariant?

RazrFalcon ★★★★★
()
Ответ на: комментарий от RazrFalcon

Как устроена работа с памятью.

Как обычно.

И как именно «обычно»?

QVariant?

По-моему, и сабж, и топик прямо таки кричат о "внутреннем" устройстве Qt. Где, как и когда выделяется/очищается память под результаты?

Edward_I
() автор топика

Какая ещё грамотная работа с памятью? Там обычный бойлерплейт - враппер.

anonymous
()
Ответ на: комментарий от RazrFalcon

Что непонятного в вопросе: где, как и когда выделяется/очищается память под результаты?

Что непонятного в выражениях: «внутреннее устройство фреймворка», «под капотом»?

Неужели не ясно, что речь идёт об понятном изложении логики работы методов классов, о невидимой цепочке действий, происходящей при видимом вызове метода, об уровне абстракции ОС/взаимодействия с ОС, а не о том, что написано в доке («вызов-результат»)?

Edward_I
() автор топика
Ответ на: комментарий от Edward_I

ну ты сам подумай кто будет писать и бесконечно поддерживать такую документацию? Правильно, никто. Поэтому ничего лучше исходников у тебя нет. С другой стороны, зачем это надо? Если ты хочешь глубоко залезть под капот, то начни например с драйвера qsqlite: https://code.woboq.org/qt5/qtbase/src/plugins/sqldrivers/sqlite/qsql_sqlite.c... . Никакой магии там нет. Просто вызов sqlite_* методов и мапирование результатов на Qt типы.

former_anonymous ★★★
()

Сделать микро-ORM под SQL - это простецкая задача, там не в чем толком разбираться. Намного сложнее отобразить эти данные в удобном настраиваемом виде или сделать прозрачное применение изменений к сложной структуре данных.

byko3y ★★★★
()
Ответ на: комментарий от Edward_I

Что непонятного в вопросе: где, как и когда выделяется/очищается память под результаты?

Так же, как и в остальных плюсах. Об этом уже писали 100500 раз.

man RAII

С одним примечательным исключением:

QWidget *widget = new MyWidget(parent);

В этом случае - перед освобождением parent. Отдельные классы могу накладывать иные правила. Читай доки.

Что непонятного в выражениях: «внутреннее устройство фреймворка», «под капотом»? Неужели не ясно, что речь идёт об понятном изложении логики работы методов классов, о невидимой цепочке действий, происходящей при видимом вызове метода, об уровне абстракции ОС/взаимодействия с ОС, а не о том, что написано в доке («вызов-результат»)?

Нету такого, это никому не нужно. Те, кто компетентен - могут читать исходники. А тем, кто некомпетентен - лезть туда нет никакой нужды.

dear_amomynous_v2_1
()

Где можно почитать о внутреннем устройстве Qt, кроме исходников?

https://woboq.com/blog/
https://doc.qt.io/qt-5/sql-programming.html

Также прошу дать ссылки на исходники грамотных Qt C++ проектов, в которых ведется работа с БД.

а что видится неграмотным в sql примерах из состава qt ?

x905 ★★★★★
()

Также прошу дать ссылки на исходники грамотных Qt C++ проектов, в которых ведется работа с БД.

В полностью установленной Qt есть два замечательных каталога — demos и examples. Там ну просто дохренища примеров несложных проектов, в том числе и по базам данных.

Есть, правда, нюанс. UI там везде конструируется напрямую в программе. Примеров с файлами .ui, по-моему, нет вообще. Это не очень типично для реальных Qt-проектов. Но с дизайнером можно и без examples разобраться.

hobbit ★★★★★
()
Ответ на: комментарий от dear_amomynous_v2_1

Так же, как и в остальных плюсах. Об этом уже писали 100500 раз.

100500 раз писали как (вот прямо так: какой размер, одноразово или поэтапно, если за несколько раз то как именно, где расположены в памяти, какую структуру имеют) , в конкретном классе (например, QSqlQuery), выделяется/освобождается память под результаты (неизвестная переменная с неизвестной структурой данных доступ к которой есть только через, выглядящие «магическими», методы)? Вопрос не о срабатывании деструктора потомка. Вопрос о работе с памятью при выполнении методов exec(), next() и т.д.

Те, кто компетентен - могут читать исходники. А тем, кто некомпетентен - лезть туда нет никакой нужды.

Читать исходники - это оверхед, когда нужно быстро разобраться с одним-двумя вопросами и общей концепцией работы смежных классов.

А кто некомпетентен - тому все равно нужно понимать где и когда выделяется/освобождается память. В доке про это мало или ничего, иначе бы тему здесь не поднимал.

Edward_I
() автор топика
Ответ на: комментарий от x905

а что видится неграмотным в sql примерах из состава qt ?

В них ничего не видится, их ещё не смотрел. Спасибо, установлю и посмотрю.

Смотрел на github'e, а там быстро нашлись только какие-то небольшие сомнительные поделки студентов. Глубже копать не стал.

Edward_I
() автор топика
Ответ на: комментарий от hobbit

В полностью установленной Qt есть два замечательных каталога — demos и examples

Спасибо. Доустановлю и посмотрю.

Edward_I
() автор топика
Ответ на: комментарий от former_anonymous

Если ты хочешь глубоко залезть под капот,

Не глубоко. Но даже то, что мне интересно (работа с памятью) в доке не освещается/плохо освещается. Хотя казалось бы - это не Java, не Python, про это стоит чуть подробнее написать.

Поэтому ничего лучше исходников у тебя нет. С другой стороны, зачем это надо?

Зачем нужно? Ну в частности вопрос возник из-за неясной для меня работы QSqlQuery (хотя касается и других классов). Вот лишь некоторые частные вопросы о нем:

1) Сколько и как выделяется память под (неизвестного размера) результаты при выполнении метода exec()? Могу ли я на этот процесс влиять или нет? В какой структуре данных хранятся результаты? Это массив указателей на динамические массивы (т.е. тоже указатели), которые указывают на что? На кортежи, на поля? А они в какой форме представлены? Выделение в памяти происходит равномерно или разбросано повсюду, разово ил поэтапно, если поэтапно, то как именно?

2) При повторном использовании exec() прошлый результат уничтожается (высвобождается память) или он висит где-то в памяти наряду с новым результатом, а высвобождение происходит только при срабатывании деструктора объекта или явном вызове clear() ?

3) Как реализован механизм «хождению» по результату типа методов next()? Кэширование данных? Но они же и так все (?) хранятся в ОЗУ. Для навигации достаточно хранить указатели на предыдущее-следующее значения. Зачем же тогда нужен метод setForwardOnly(), который как указано в доке: "Forward only mode can be (depending on the driver) more memory efficient since results do not need to be cached. Что там такого происходит, что сразу more memory efficient?

Мне не кажется, что это какие-то особо каверзные и глубокие вопросы, которые не нужно знать пользователю Qt. Это вполне естественные вопросы, ответы на которые дадут мне понять как правильно (а не как «вообще») работать c этими классами, чтобы приложение у меня не съедало Gb-ы RAM. У меня есть свои догадки как это все реализовано, но хотелось знать, а не догадываться.

Никакой магии там нет.

Нет. Понимаю. Только это (судя по доке и книгам/статьям о Qt) тщательно скрывают.

Edward_I
() автор топика
Ответ на: комментарий от Edward_I

Такой информации нет почти ни в какой документации. Это всё только на практике выясняется.
А так как у кутэ вроде есть платная версия, то эти вопросы скрывают для того что бы ты обращался в платную поддержку.

Bad_ptr ★★★★★
()
Ответ на: комментарий от Bad_ptr

Это всё только на практике выясняется.

Пока пришел к выводу, что ответы смогу получить:
1) в исходниках
2) чужой код (чужая практика)
3) проводя эксперименты с профилированием

Но всё это пока оверхед. Не оставляю надежды получить информацию в «разжёванном» виде.

А так как у кутэ вроде есть платная версия, то эти вопросы скрывают для того что бы ты обращался в платную поддержку.

Пока думал о вопросе, забыл про платную версию. А ларчик-то просто открывается.

Edward_I
() автор топика
Ответ на: комментарий от Edward_I

Вряд ли вы найдете ответы на эти вопросы в готовом виде, т.к. они не имеют никакой практической ценности. И могут быть получены только для конкретной версии под конкретную платформу. А могут вообще зависеть от драйвера БД. Зачем вам знать, сколько выделяется памяти, вам ее не хватает ? Тогда лучше вообще отказаться от QtSQL и работать с API БД.

Qt тем и замечателен, что все скрывает под капотом, а снаружи везде одинаковый.

Работа с SQL в Qt сделана очень плохо, пригодно только для демонстрации.

Serik
()
Ответ на: комментарий от Bad_ptr

Такой информации нет почти ни в какой документации.

У меня два вопроса:

- Не считаете ли вы такую информацию какой-то особо ненужной/сложной/глубокой? Нормальные же вопросы я задаю, не излишние? Просто я искренне не понимаю, а что такого многого я хочу узнать или что такого трудного нельзя было двумя фразами описать в документации.

- А вы, в общем, считаете нормальным, что там, где ответственность за память возложена на разработчика, в документации ничего не говориться (или мало что) про память?

Edward_I
() автор топика
Ответ на: комментарий от Serik

Зачем вам знать, сколько выделяется памяти, вам ее не хватает ?

Если на выделение/освобождение можно повлиять, если этот процесс может отличаться на порядки (а я не знаю отличается или нет) при тех или иных вводных, тех или иных вызовах методов, то хотелось бы это знать и учитывать. Впрочем сколько - может и не так важно. Однако, процесс высвобождения - это уже важно.

Тогда лучше вообще отказаться от QtSQL и работать с API БД

Если нет API? Если она embedded? Работать с сишными драйверами?

Работа с SQL в Qt сделана очень плохо, пригодно только для демонстрации.

Какие остаются варианты? Писать свои классы поверх сишных либ?
Ну допустим. Но хотелось бы прежде понять: а стоит ли оно того? Насколько (и что именно) в Qt неэффективно, чтобы стоило переходить на более низкий уровень. И тут опять же возникают мои вопросы.

Edward_I
() автор топика

Qt - игрушечный фреймворк. Вся суть его использования сводится к тому, чтоб нагуглить хоть какой-то пример и методом тыка допинать его до нужного функционала. Поэтому внутри у него кромешный ад из подпорок, автоматическое управление памятью и куча неудачных архитектурных решений. Если у ТС есть время и желание разбираться в деталях, лучше взять другую библиотеку, в которой эти детали выставлены в интерфейс, а не заныканы по приватным хедерам подальше от дурачков узеров, как в Qt.

q0tw4 ★★★★
()
Ответ на: комментарий от Serik

Работа с SQL в Qt сделана очень плохо, пригодно только для демонстрации.

какой пример из поставки демонстрирует это «плохо» ?

x905 ★★★★★
()
Ответ на: комментарий от x905

Во-первых код с pimpl невозможно читать, заколебаешься прыгать по методам. Во-вторых бывает надо дернуть что-то из приватного хедера/сорца. Приходится копировать код в свой проект, чтоб по чесноку было. В-третих когда наружу торчит одна большая кнопка, типа нарисуй мне SVG-шку из такого-то файла дико не хватает доступа к DOM модели этой SVG-шки. Ну и так много где. Qt местами реально напоминает идеальную программу с одной кнопкой «сделай пейсато». Вот только для сурьезного кодера это жутко неудобно. Открытость сорцов должна быть не только в возможности их читать, но и в возможности запускать и подменять функционал либы из кода приложения.

q0tw4 ★★★★
()

Keep calm

энд читай исходники QSqlDriver. Если понимание внутреннего устройства, а не флуд есть самоцель - то это лучший источник.

pon4ik ★★★★★
()
Ответ на: Keep calm от pon4ik

Думаю в случае с Qt хватит внимательно почитать документацию по классам. Там все, что нужно знать узеру вполне доступно описано. То, что не сказано в документации есть внутренняя кухня, глубоко вникать в которую опасно для психики.

q0tw4 ★★★★
()
Ответ на: комментарий от q0tw4

Да да, то-то тут столько неосиливших понять как устроен QEventLoop в общем и QCoreApplication::exec в частности, и чем политики соединения сигналов со слотами отличаются. В год по 10 тем набегает бывает.

pon4ik ★★★★★
()
Последнее исправление: pon4ik (всего исправлений: 1)
Ответ на: комментарий от q0tw4

Дырявые абстракции хороши для библиотеки, и то не всегда. Фреймворк на то и фреймворк что бы по рельсам его ехать к победе и единообразию решений.

pon4ik ★★★★★
()
Ответ на: комментарий от x905

pimpl - попытка подтянуть язык с текстовым инклудом хидеров к стандартам индустрии вроде джавы (где можно смело писать все в приват классу и менять сколько душе угодно). Просто смените язык, делов то, но нет, будем мучать труп.

q0tw4 ★★★★
()
Последнее исправление: q0tw4 (всего исправлений: 1)
Ответ на: комментарий от Edward_I

Какие остаются варианты? Писать свои классы поверх сишных либ?

Если вас беспокоит эффективность, то это единственный правильный путь. И в этом нет ничего сложного.

Ну допустим. Но хотелось бы прежде понять: а стоит ли оно того? Насколько (и что именно) в Qt неэффективно, чтобы стоило переходить на более низкий уровень. И тут опять же возникают мои вопросы.

Какие вопросы, вы пользуетесь Qt и не знаете, что в ней не эффективно ? Значит все эффективно. :)

Я вообще не про эффективность, а про функциональность: управление транзакциями, параметризированные запросы, хранение подготовленных запросов и т.д.

Serik
()
Ответ на: комментарий от q0tw4

pimpl - попытка подтянуть язык с текстовым инклудом хидеров к стандартам индустрии

какой язык есть, такой и используется, это не обсуждается

но ты так и не рассказал про игрушечность qt и кучу неудачных архитектурных решений в нем
а приведи пример библиотеки (уровня qt) где их нет - ее ТС и начнет использовать

x905 ★★★★★
()
Ответ на: комментарий от x905

Ну например почему инвалидный QModelIndex представляет root дерева? К нему же нельзя прикрепить user pointer. Да и вообще возвращать QVariant в таблицах для статически типизированного языка как-то... Я лично писал либу, которая шаблонами задаёт типы значения каждого столбца, это вполне рабочая схема для плюсов. Короче в Qt все ставят на простоту использования (если не считать корявых ItemModel с делегатами, в которых как раз черт ногу сломит), а на элегантность архитектуры им плевать.

q0tw4 ★★★★
()
Ответ на: комментарий от q0tw4

Да и вообще возвращать QVariant в таблицах для статически типизированного языка как-то...

это ты про SQL ?

x905 ★★★★★
()
Ответ на: комментарий от q0tw4

Вот только для сурьезного кодера это жутко неудобно.

Не тяни субъетивные хотелки на всех разрабов.

Открытость сорцов должна быть не только в возможности их читать, но и в возможности запускать и подменять функционал либы из кода приложения.

Qt архитектура не идеальна, но весьма неплоха. Где нужна низкоуровневость - бери соответствующую либу, где устраивает подход Qt - милости прошу. А бравады «у них должно быть так-то», «архитектура не такая» - какой-то детский сад и инфантильность.

rumgot ★★★★★
()
Ответ на: комментарий от q0tw4

а на элегантность архитектуры им плевать

Твое восприятие и элегантность - синонимы только в твоем мире.

rumgot ★★★★★
()
Ответ на: комментарий от q0tw4

И оно есть, по крайней мере было…

Только за деньги, не всёж бомжей неосиляторов кормить.

pon4ik ★★★★★
()

Где можно почитать о внутреннем устройстве Qt, кроме исходников?

спросить в почтовой рассылке

https://blog.qt.io/

https://woboq.com/blog/

https://www.kdab.com/category/blogs/

Также прошу дать ссылки на исходники грамотных Qt C++ проектов, в которых ведется работа с БД.

https://github.com/KDAB/sqlate/

fluorite ★★★★★
()
Ответ на: комментарий от Edward_I

Читать исходники - это оверхед

Нет, так кажется только начинающим разработчикам. С опытом навык развивается и чтение исходного кода становится даже менее трудоёмким, чем документации (потому что последняя всегда врёт).

fluorite ★★★★★
()
Ответ на: комментарий от Edward_I

1) Сколько и как выделяется память под (неизвестного размера) результаты при выполнении метода exec()? Могу ли я на этот процесс влиять или нет? В какой структуре данных хранятся результаты? Это массив указателей на динамические массивы (т.е. тоже указатели), которые указывают на что? На кортежи, на поля? А они в какой форме представлены? Выделение в памяти происходит равномерно или разбросано повсюду, разово ил поэтапно, если поэтапно, то как именно?

Вот смотри, немножко исходников:

bool QSqlQuery::exec(const QString& query)
{
  ...
  *this = QSqlQuery(driver()->createResult());
  ...
смотрим, что такое createResult()
virtual QSqlResult *createResult() const = 0;
Т.е. ответ: результат exec() и есть QSqlQuery, реализация зависит от драйвера.

fluorite ★★★★★
()
Ответ на: комментарий от Serik

А могут вообще зависеть от драйвера БД

this

На C пиши. А лучше сразу на асме. Ты я вижу любитель преждевременных оптимизаций.

anonymous
()
Ответ на: комментарий от q0tw4

Я лично писал либу, которая шаблонами

Qt существует с 1996 года. Применяемые решения во многом определяются тем C++, который был тогда.

anonymous
()
Ответ на: комментарий от Edward_I

100500 раз писали как (вот прямо так: какой размер, одноразово или поэтапно, если за несколько раз то как именно, где расположены в памяти, какую структуру имеют) , в конкретном классе (например, QSqlQuery), выделяется/освобождается память под результаты (неизвестная переменная с неизвестной структурой данных доступ к которой есть только через, выглядящие «магическими», методы)? Вопрос не о срабатывании деструктора потомка. Вопрос о работе с памятью при выполнении методов exec(), next() и т.д.

Этого не было, нет и не будет.

Читать исходники - это оверхед, когда нужно быстро разобраться с одним-двумя вопросами и общей концепцией работы смежных классо

Оверхед - это то, чего ты просишь, - переписывания исходников на человеческом языке. Никто и никогда не будет этим заниматься, потому что трудозатраты колоссальны, а профит получит только парочка дилетантов, неспособных читать код.

А кто некомпетентен - тому все равно нужно понимать где и когда выделяется/освобождается память. В доке про это мало или ничего, иначе бы тему здесь не поднимал.

Нет, не нужно. Абстракции специально сделаны что бы программист по другую сторону интерфейса не задавался такими вопросами.

dear_amomynous_v2_1
()
Ответ на: комментарий от dear_amomynous_v2_1

Нет, не нужно. Абстракции специально сделаны что бы программист по другую сторону интерфейса не задавался такими вопросами.

В случае с Qt так оно и есть. Хотя в некоторых местах таки надо понимать что происходит, иначе будет непонятно как это использовать. Например при управлении памятью куобжектов в отношениях родитель-ребенок и, например что делает moveToThread. Но в подобных случаях в офдоках достаточно инфы.

q0tw4 ★★★★
()
Ответ на: комментарий от Edward_I

об уровне абстракции ОС/взаимодействия с ОС

а причём тут оно, если в SQL запросе этим занимается не Qt, а драйвер БД?

Qt-шные классы - это просто обёртка и никто по её кишкам доков не писал, проще исходники глянуть, а самое главное, никто не гарантирует, что кишки это обёртки будут работать единообразно в разных версиях Qt

next_time ★★★★★
()
Ответ на: комментарий от next_time

ORM, умеющие в Qt уже есть

Примерчик бы, спасибопожалста.. а то все, что я встречал, слегка окаменело

aol ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.