Cool RJ :-)

It was always there but I never noticed:
http://qt-project.org/doc/qt-4.8/qstring.html#more-efficient-string-construction

Let us use this!




2013/5/1 RJ Ryan <[email protected]>

>
>
>
> On Wed, May 1, 2013 at 4:03 PM, Daniel Schürmann <[email protected]>wrote:
>
>> Hi,
>>
>> the typo resistance is an other good point for using constants.
>>
>> ---
>>
>> The performance win does not happen when issue a query, it happens when
>> starting Mixxx.
>>
>> const QString LIBRARYTABLE_ID = "id";
>>
>> "id" is in text segment after starting Mixxx. The QString constructor
>> converts the string to 16 bit unicode and stores it on the heap after
>> malloc.
>>
>> const char* = "id";
>>
>> is simply a pointer to the text segment.
>>
>
> Ah, yes -- I agree there is a cost (again, tiny) during global
> initialization. I was referring to the cost of constructing the SQL query
> in Steven's example though.
>
> #define PLAYLIST_TABLE  "PlaylistTracks"
>
> QString sqlQuery = QString("SELECT FROM " PLAYLIST_TABLE " ...");
>
> This is 1 malloc and no concatenation. The compiler joins the multiple
> string literals together into one string literal.
>
> Whereas
>
> const QString PLAYLIST_TABLE = "PlaylistTracks";
>
> QString sqlQuery = QString("SELECT FROM " + PLAYLIST_TABLE + "...");
>
> Involves potentially 2 mallocs before the outer QString constructor is
> called (the outer QString will probably use Qt's implicit sharing so no
> malloc will happen).
>
> Since often in the DAOs very long queries are constructed by strings of +
> operators and QString string interpolation, there is a whole lot of malloc
> and copy going on every time we want to format a query.
>
> I still say it's negligible compared to any real work going on -- but
> relative to global static initialization (a one time cost at bootup on the
> order of tens of microseconds, max) I would say this is much more expensive
> since it happens every time we construct a query and often does a lot more
> work than a single malloc / memcpy.
>
> I read a post a while back about QStringBuilder. In Qt 4.6 you can
> basically define QT_USE_QSTRINGBUILDER and it converts QString's operator +
> to use lazy evaluation. We may as well turn that on?
>
> http://blog.qt.digia.com/blog/2011/06/13/string-concatenation-with-qstringbuilder/
>
>
>
>>
>> I am also not sure if putting this to trackdao.h will duplicate the
>> sting in text segment each time trackdao.h is included. So we should make
>> them static members of TrackDAO to be sure.
>>
>
> The QString definitions will appear in the data section of every .o that
> includes trackdao.h. Ideally the linker would collapse the duplicates but
> I'm guessing it doesn't :). Someone could easily check by running 'strings'
> on the mixxx binary.
>
>
>> Just two cents from an embedded developer ;-)
>>
>> Kind regards,
>>
>> Daniel
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>>
>> 2013/5/1 RJ Ryan <[email protected]>
>>
>>> The main reason for me is that they are a protection measure against
>>> making typos in SQL queries. You'd think a typo would get noticed but not
>>> all queries fail immediately when they have a mistake in them. Some of them
>>> just return no results, or return wrong results. For queries that are off
>>> the beaten path, we end up with issues like 
>>> this<https://bugs.launchpad.net/mixxx/+bug/1175024>(which Steven just 
>>> fixed).
>>>
>>> In fact, I would prefer we totally got rid of writing SQL queries
>>> directly in code and instead composed them using declarative C++ classes
>>> which are then compiled down to SQL. Not quite a full-on ORM, just
>>> something for composing SQL queries (like SQLAlchemy for C++).
>>>
>>>
>>> On Wed, May 1, 2013 at 2:56 PM, Owen Williams <[email protected]>wrote:
>>>
>>>> Are the constants really a good idea?  What is the purpose behind using
>>>> them?  Ideally the schema shouldn't be changing very often so having
>>>> them hardcoded seems ok from a maintenance perspective.  And from a
>>>> readability perspective, the constant method looks really ugly to me.
>>>> I'm just wondering what the other side of the argument is.
>>>>
>>>> owen
>>>>
>>>> On Wed, 2013-05-01 at 14:42 -0400, RJ Ryan wrote:
>>>> > On Wed, May 1, 2013 at 2:15 PM, Daniel Schürmann <[email protected]>
>>>> > wrote:
>>>> >         Hi Steven,
>>>> >
>>>> >         Yes, we should solve this issue and use the const values in
>>>> >         any case.
>>>> >         This allows to rely on IDE features like "display call tree".
>>>> >
>>>> >
>>>> >
>>>> > I think we should stick with whatever makes the code easiest to
>>>> > maintain (which would be using the constants when possible) -- maybe
>>>> > the constants should be renamed to be a little easier on the eyes? A
>>>> > lot of the DAO code doesn't use the constants, that's true. We should
>>>> > fix those queries.
>>>> >
>>>> >
>>>> >         But I am not sure if the use of const QString is performance
>>>> >         neutral to const char* and #define because the heavy QSting
>>>> >         constructor is called.
>>>> >
>>>> >         So IMHO we should change it to const char*.
>>>> >
>>>> >
>>>> > There are a lot of non-performance-neutral choices we make in Mixxx,
>>>> > but that alone isn't enough to make a decision, we have to take the
>>>> > context into account. Compared to the QSqlQuery::exec() that comes
>>>> > immediately after all these queries, some string concatenation isn't
>>>> > going to break the bank, cycle-wise. Processors are pretty good at
>>>> > memcpy these days :).
>>>> >
>>>> >
>>>> >         Kind regards,
>>>> >
>>>> >         Daniel
>>>> >
>>>> >
>>>> >
>>>> >
>>>> >
>>>> >         Am 01.05.2013 17:32, schrieb Steven Boswell II:
>>>> >
>>>> >         > Most of the DAO header files in src/library/dao have
>>>> >         > definitions for the names of tables, and the names of
>>>> >         > columns in the tables, but they're used sporadically; quite
>>>> >         > often, references to them are hardcoded.
>>>> >         >
>>>> >         >
>>>> >         > I'm writing a new feature (the aforementioned
>>>> >         > auto-DJ-crates), and the necessary info is stored in a
>>>> >         > temporary table, so I'm writing several SQL queries.  I'm
>>>> >         > just wondering if I should hardcode the table/column
>>>> >         > references (which won't automatically get updated if the
>>>> >         > underlying names change), or try to write them using the
>>>> >         > table/column names defined in header files (which makes the
>>>> >         > query harder to read).
>>>> >         >
>>>> >         >
>>>> >         > Here's an example.  The comment is the hardcoded,
>>>> >         > human-readable version, and following it is the hard-to-read
>>>> >         > one that'll adapt automatically to changes.
>>>> >         >
>>>> >         >
>>>> >         >
>>>> >         >     // INSERT INTO temp_autodj_crates (track_id, craterefs,
>>>> >         > timesplayed, autodjrefs) SELECT crate_tracks.track_id, COUNT
>>>> >         > (*), library.timesplayed, 0 FROM crate_tracks, library WHERE
>>>> >         > crate_tracks.crate_id IN (SELECT id FROM crates WHERE autodj
>>>> >         > = 1) AND crate_tracks.track_id = library.id AND
>>>> >         > library.mixxx_deleted = 0 GROUP BY crate_tracks.track_id,
>>>> >         > library.timesplayed;
>>>> >         >     strQuery = QString ("INSERT INTO " AUTODJCRATES_TABLE
>>>> >         >         " (" AUTODJCRATESTABLE_TRACKID ", "
>>>> >         > AUTODJCRATESTABLE_CRATEREFS ", "
>>>> >         >         AUTODJCRATESTABLE_TIMESPLAYED ", "
>>>> >         > AUTODJCRATESTABLE_AUTODJREFS ")"
>>>> >         >         " SELECT " CRATE_TRACKS_TABLE ".%1 , COUNT (*), "
>>>> >         >         LIBRARY_TABLE ".%2, 0 FROM " CRATE_TRACKS_TABLE ", "
>>>> >         > LIBRARY_TABLE
>>>> >         >         " WHERE " CRATE_TRACKS_TABLE ".%4 IN "
>>>> >         >         "(SELECT %5 FROM " CRATE_TABLE " WHERE %6 = 1) AND "
>>>> >         >         CRATE_TRACKS_TABLE ".%1 = " LIBRARY_TABLE ".%7 AND "
>>>> >         > LIBRARY_TABLE
>>>> >         >         ".%3 == 0 GROUP BY " CRATE_TRACKS_TABLE ".%1, "
>>>> >         > LIBRARY_TABLE ".%2")
>>>> >         >             .arg (CRATETRACKSTABLE_TRACKID)        // %1
>>>> >         >             .arg (LIBRARYTABLE_TIMESPLAYED)        // %2
>>>> >         >             .arg (LIBRARYTABLE_MIXXXDELETED)    // %3
>>>> >         >             .arg (CRATETRACKSTABLE_CRATEID)        // %4
>>>> >         >             .arg (CRATETABLE_ID)                // %5
>>>> >         >             .arg (CRATETABLE_AUTODJ)            // %6
>>>> >         >             .arg (LIBRARYTABLE_ID);                // %7
>>>> >         >
>>>> >         >
>>>> >         >
>>>> >         > Which should I do?
>>>> >         >
>>>> >         >
>>>> >         > Pretty soon, I'll make a blueprint for the auto-DJ-crates
>>>> >         > feature.
>>>> >         >
>>>> >         >
>>>> >         >
>>>> >         > Steven Boswell
>>>> >         >
>>>> >         >
>>>> >         >
>>>> >         >
>>>> >         >
>>>> ------------------------------------------------------------------------------
>>>> >         > Introducing AppDynamics Lite, a free troubleshooting tool
>>>> for Java/.NET
>>>> >         > Get 100% visibility into your production application - at
>>>> no cost.
>>>> >         > Code-level diagnostics for performance bottlenecks with <2%
>>>> overhead
>>>> >         > Download for free and get started troubleshooting in
>>>> minutes.
>>>> >         > http://p.sf.net/sfu/appdyn_d2d_ap1
>>>> >         >
>>>> >         >
>>>> >         > _______________________________________________
>>>> >         > Get Mixxx, the #1 Free MP3 DJ Mixing software Today
>>>> >         > http://mixxx.org
>>>> >         >
>>>> >         >
>>>> >         > Mixxx-devel mailing list
>>>> >         > [email protected]
>>>> >         > https://lists.sourceforge.net/lists/listinfo/mixxx-devel
>>>> >
>>>> >
>>>> >
>>>> >
>>>> ------------------------------------------------------------------------------
>>>> >         Introducing AppDynamics Lite, a free troubleshooting tool for
>>>> >         Java/.NET
>>>> >         Get 100% visibility into your production application - at no
>>>> >         cost.
>>>> >         Code-level diagnostics for performance bottlenecks with <2%
>>>> >         overhead
>>>> >         Download for free and get started troubleshooting in minutes.
>>>> >         http://p.sf.net/sfu/appdyn_d2d_ap1
>>>> >         _______________________________________________
>>>> >         Get Mixxx, the #1 Free MP3 DJ Mixing software Today
>>>> >         http://mixxx.org
>>>> >
>>>> >
>>>> >         Mixxx-devel mailing list
>>>> >         [email protected]
>>>> >         https://lists.sourceforge.net/lists/listinfo/mixxx-devel
>>>> >
>>>> >
>>>> >
>>>> ------------------------------------------------------------------------------
>>>> > Introducing AppDynamics Lite, a free troubleshooting tool for
>>>> Java/.NET
>>>> > Get 100% visibility into your production application - at no cost.
>>>> > Code-level diagnostics for performance bottlenecks with <2% overhead
>>>> > Download for free and get started troubleshooting in minutes.
>>>> > http://p.sf.net/sfu/appdyn_d2d_ap1
>>>> > _______________________________________________ Get Mixxx, the #1
>>>> Free MP3 DJ Mixing software Today http://mixxx.org Mixxx-devel mailing
>>>> list [email protected]
>>>> https://lists.sourceforge.net/lists/listinfo/mixxx-devel
>>>>
>>>>
>>>>
>>>
>>
>
------------------------------------------------------------------------------
Introducing AppDynamics Lite, a free troubleshooting tool for Java/.NET
Get 100% visibility into your production application - at no cost.
Code-level diagnostics for performance bottlenecks with <2% overhead
Download for free and get started troubleshooting in minutes.
http://p.sf.net/sfu/appdyn_d2d_ap1
_______________________________________________
Get Mixxx, the #1 Free MP3 DJ Mixing software Today
http://mixxx.org


Mixxx-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/mixxx-devel

Reply via email to