dbTalk Databases Forums  

Optimization of Row (patch attached)

mailing.database.mysql-plusplus mailing.database.mysql-plusplus


Discuss Optimization of Row (patch attached) in the mailing.database.mysql-plusplus forum.



Reply
 
Thread Tools Display Modes
  #1  
Old   
Byrial Jensen
 
Posts: n/a

Default Optimization of Row (patch attached) - 05-29-2005 , 12:28 PM






--------------050404000207060504030002
Content-Type: text/plain; charset=us-ascii; format=flowed
Content-Transfer-Encoding: 7bit

Hi,

When a Row object is constructed, it will copy all data of the fetched
row of type MYSQL_ROW to a vector of std::string. That seems to me as
unnecessary use of time and memory. The row data is only accessed
through pointers to const char:
* Row::raw_data() returns a pointer obtained from std::string::data()
* Row:perator[]() uses a pointer obtained from std::tring::c_str()
to initialize the returned ColData object.

The attached patch will store the MYSQL_ROW and directly get the
pointers to data from it in raw_data() and operator[]().

There should be only one visible change to the endusers, and
that is a good one:
* The pointer returned by raw_data() will with the patch point to a
NUL-terminated string (coming directly from the MYSQL_ROW object given
by mysql_fetch_row()). The pointer currently returned is fetched by
std::string::data() and therefore not NUL-terminated. This change means
that a user who wants a raw pointer to a NUL-terminated column data, now
can use raw_data() instead of creating of a ColData object with
operator[]() - which also copies the data - and in that way avoid that
data from, say, large BLOB database types is copied twice.

I have a program where this patch gives more than 20 % decrease of the
execution time (from 99 down to 77 seconds) when it runs on an otherwise
idle Linux box.

Best regards
Byrial


--------------050404000207060504030002
Content-Type: text/x-patch;
name="row.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="row.patch"

diff -upr mysql++-1.7.40.orig/lib/row.cpp mysql++-1.7.40/lib/row.cpp
--- mysql++-1.7.40.orig/lib/row.cpp 2005-05-25 03:41:48.000000000 +0200
+++ mysql++-1.7.40/lib/row.cpp 2005-05-29 07:19:24.806953357 +0200
@@ -43,8 +43,9 @@ const ColData Row:perator [](size_type
else
return ColData();
}
-
- return ColData(data.at(i).c_str(), res->types(i), is_nulls[i]);
+ if (i >= no_of_columns)
+ throw std:ut_of_range("Row index out of range");
+ return ColData(data[i] ? data[i] : "NULL", res->types(i), ! data[i]);
}

const ColData Row::lookup_by_name(const char* i) const
diff -upr mysql++-1.7.40.orig/lib/row.h mysql++-1.7.40/lib/row.h
--- mysql++-1.7.40.orig/lib/row.h 2005-05-26 06:02:55.000000000 +0200
+++ mysql++-1.7.40/lib/row.h 2005-05-29 07:27:02.625432077 +0200
@@ -483,8 +483,8 @@ class Row : public const_subscript_conta
const ColData>, public RowTemplate<Row, ResUse>
{
private:
- std::vector<std::string> data;
- std::vector<bool> is_nulls;
+ MYSQL_ROW data;
+ size_type no_of_columns;
const ResUse* res;
bool throw_exceptions;
bool initialized;
@@ -500,6 +500,7 @@ public:
/// \param jj length of each item in d
/// \param te if true, throw exceptions on errors
Row(MYSQL_ROW d, const ResUse* r, unsigned long* jj, bool te = false) :
+ data(d),
res(r),
throw_exceptions(te),
initialized(false)
@@ -512,21 +513,13 @@ public:
return;
}
}
- data.clear();
- is_nulls.clear();
+ no_of_columns = size();
initialized = true;
- for (unsigned int i = 0; i < size(); i++) {
- data.insert(data.end(),
- (d[i] ? std::string(d[i], jj[i]) : std::string("NULL")));
- is_nulls.insert(is_nulls.end(), d[i] ? false : true);
- }
}

/// \brief Destroy object
~Row()
{
- data.clear();
- is_nulls.clear();
initialized = false;
}

@@ -597,13 +590,13 @@ public:
/// check for out-of-bounds array indices.
const char* raw_data(int i) const
{
- return data[i].data();
+ return data[i] ? data[i] : "NULL";
}

/// \brief Returns true if there is data in the row.
operator bool() const
{
- return data.size();
+ return no_of_columns;
}
};




--------------050404000207060504030002
Content-Type: text/plain; charset=us-ascii

--
MySQL++ Mailing List
For list archives: http://lists.mysql.com/plusplus
To unsubscribe: http://lists.mysql.com/plusplus?unsu...ie.nctu.edu.tw
--------------050404000207060504030002--

Reply With Quote
  #2  
Old   
Chris Frey
 
Posts: n/a

Default Re: Optimization of Row (patch attached) - 05-29-2005 , 02:41 PM






On Sun, May 29, 2005 at 07:28:16PM +0200, Byrial Jensen wrote:
Quote:
Hi,

When a Row object is constructed, it will copy all data of the fetched
row of type MYSQL_ROW to a vector of std::string. That seems to me as
unnecessary use of time and memory. The row data is only accessed
through pointers to const char:
Something to remember is that Row objects are stored in containers
when using SSQLS, as far as I can tell, so this would create a hidden
dependency on the Result object: all Row object data would disappear if
their lifetimes exceeded the lifetime of the corresponding Result.

i.e. The Result destructor calls mysql_free_result() via Result:urge().


Quote:
I have a program where this patch gives more than 20 % decrease of the
execution time (from 99 down to 77 seconds) when it runs on an otherwise
idle Linux box.
This is pretty cool, but perhaps it would be better served with a new
row object that is optimized for this. This is up to Warren, but 20%
is a nice chunk of CPU time.

- Chris


--
MySQL++ Mailing List
For list archives: http://lists.mysql.com/plusplus
To unsubscribe: http://lists.mysql.com/plusplus?unsu...ie.nctu.edu.tw



Reply With Quote
  #3  
Old   
Chris Frey
 
Posts: n/a

Default Re: Optimization of Row (patch attached) - 05-29-2005 , 06:15 PM



On Sun, May 29, 2005 at 03:41:39PM -0400, Chris Frey wrote:
Quote:
I have a program where this patch gives more than 20 % decrease of the
execution time (from 99 down to 77 seconds) when it runs on an otherwise
idle Linux box.

This is pretty cool, but perhaps it would be better served with a new
row object that is optimized for this. This is up to Warren, but 20%
is a nice chunk of CPU time.
Actually, after some thought, an iterator into a Result would be the most
logical way to access this, and would indicate it depends on the Result,
and could be fast.

I don't think this exists yet in mysql++.

- Chris


--
MySQL++ Mailing List
For list archives: http://lists.mysql.com/plusplus
To unsubscribe: http://lists.mysql.com/plusplus?unsu...ie.nctu.edu.tw



Reply With Quote
  #4  
Old   
Byrial Jensen
 
Posts: n/a

Default Re: Optimization of Row (patch attached) - 05-30-2005 , 09:24 AM



Chris Frey wrote:
Quote:
On Sun, May 29, 2005 at 07:28:16PM +0200, Byrial Jensen wrote:

Hi,

When a Row object is constructed, it will copy all data of the fetched
row of type MYSQL_ROW to a vector of std::string. That seems to me as
unnecessary use of time and memory. The row data is only accessed
through pointers to const char:


Something to remember is that Row objects are stored in containers
when using SSQLS, as far as I can tell, so this would create a hidden
dependency on the Result object: all Row object data would disappear if
their lifetimes exceeded the lifetime of the corresponding Result.

i.e. The Result destructor calls mysql_free_result() via Result:urge().
You have a good point. However the functions Row:arent(), Row::size(),
Row:perator bool(), Row:perator[]() and Row::lookup_by_name() are
already now dependent on the parent Result object - it gives undefined
behavour to use these functions after the destruction of the Result.

The only useful member function left which now can be used without the
parent is Row::raw_data().

If the lifetime of a Row object really is expected to be able to extend
the lifetime of the parent Result object, I would suggest a rewrite to
remove the current dependencies.

Best regards,
Byrial

--
MySQL++ Mailing List
For list archives: http://lists.mysql.com/plusplus
To unsubscribe: http://lists.mysql.com/plusplus?unsu...ie.nctu.edu.tw



Reply With Quote
  #5  
Old   
Chris Frey
 
Posts: n/a

Default Re: Optimization of Row (patch attached) - 05-31-2005 , 11:14 AM



On Mon, May 30, 2005 at 04:23:56PM +0200, Byrial Jensen wrote:
Quote:
You have a good point. However the functions Row:arent(), Row::size(),
Row:perator bool(), Row:perator[]() and Row::lookup_by_name() are
already now dependent on the parent Result object - it gives undefined
behavour to use these functions after the destruction of the Result.

The only useful member function left which now can be used without the
parent is Row::raw_data().
Good point.

Quote:
If the lifetime of a Row object really is expected to be able to extend
the lifetime of the parent Result object, I would suggest a rewrite to
remove the current dependencies.
I'm favouring a speedy iterator which gives a dependent row object,
and could then be copied into a standalone Row at the user's discretion.

But I'd need to study the code a bit more to untangle it fully. An argument
could be made that SSQLS serves the copying purpose of Row, and that Row
should be dependent anyway, since it is a core object. This would make sense
and be consistent with the rest of the library, where things depend on
connection in hidden ways.

- Chris


--
MySQL++ Mailing List
For list archives: http://lists.mysql.com/plusplus
To unsubscribe: http://lists.mysql.com/plusplus?unsu...ie.nctu.edu.tw



Reply With Quote
  #6  
Old   
Warren Young
 
Posts: n/a

Default Re: Optimization of Row (patch attached) - 07-08-2005 , 03:39 AM



Chris Frey wrote:

Quote:
Actually, after some thought, an iterator into a Result would be the most
logical way to access this,
I went looking into the current result iterator stuff (resiter.h) and it
seems that you can already get a row object by reference this way.
Byrial, can you please try this and see if it also reduces your
program's run time?

If you're using 'use' queries, you can't use this iterator, but there's
already a plan to add iterators for those as well.

--
MySQL++ Mailing List
For list archives: http://lists.mysql.com/plusplus
To unsubscribe: http://lists.mysql.com/plusplus?unsu...ie.nctu.edu.tw



Reply With Quote
  #7  
Old   
Warren Young
 
Posts: n/a

Default Re: Optimization of Row (patch attached) - 07-08-2005 , 04:08 AM



Warren Young wrote:

Quote:
I went looking into the current result iterator stuff
....and didn't understand it on first look. Nevermind, you two. I'm
just confused.

--
MySQL++ Mailing List
For list archives: http://lists.mysql.com/plusplus
To unsubscribe: http://lists.mysql.com/plusplus?unsu...ie.nctu.edu.tw



Reply With Quote
Reply




Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

vB code is On
Smilies are On
[IMG] code is On
HTML code is Off



Powered by vBulletin Version 3.5.3
Copyright ©2000 - 2012, Jelsoft Enterprises Ltd.