| View previous topic :: View next topic |
| Author |
Message |
Les Pawelczyk Guest
|
Posted: Wed Apr 19, 2006 6:03 pm Post subject: FieldByName |
|
|
In my quest to speed-up application that loads lots of data from database during start-up I took a look at TDataSet.FieldByName. It seems that it eventually finds its way to TFields.FindField which makes use of AnsiCompareText inside loop which goes through all the fields. AnsiCompareText calls CompareString which is a Windows API. I replaced AnsiCompareText with my own ASM version that uses lookup tables. It seems that FieldByName now executes 30% to 50% faster. That gives this particular application performance improvement much greater than what FastMM4 and FastMove can do combined.
Anybody else curious to try it?
Les. |
|
| Back to top |
|
 |
John O'Harrow Guest
|
Posted: Wed Apr 19, 2006 7:03 pm Post subject: Re: FieldByName |
|
|
"John Herbster" <herb-sci1_at_sbcglobal.net> wrote in message
news:4446774b$1 (AT) newsgroups (DOT) borland.com...
| Quote: |
"Les Pawelczyk" wrote
In my quest to speed-up application that loads lots of data from
database during start-up I took a look at TDataSet.FieldByName.
Aside from your interesting investigation, when my code would
otherwise make lots of FieldByName() lookups, I declare some
variables to hold the pointers to the field objects, load them with
the addresses of the field objects at runtime just ofter opening
the table, and then use them whenever the fields need to be
referenced. --JohnH
|
I do exactly the same - Just one call to FieldByName for each field at
start-up.
--
regards,
John
The Fastcode Project:
http://www.fastcodeproject.org/ |
|
| Back to top |
|
 |
John Herbster Guest
|
Posted: Wed Apr 19, 2006 7:03 pm Post subject: Re: FieldByName |
|
|
"Les Pawelczyk" wrote
| Quote: | In my quest to speed-up application that loads lots of data from
database during start-up I took a look at TDataSet.FieldByName.
|
Aside from your interesting investigation, when my code would
otherwise make lots of FieldByName() lookups, I declare some
variables to hold the pointers to the field objects, load them with
the addresses of the field objects at runtime just ofter opening
the table, and then use them whenever the fields need to be
referenced. --JohnH |
|
| Back to top |
|
 |
John Herbster Guest
|
Posted: Wed Apr 19, 2006 8:03 pm Post subject: Re: FieldByName |
|
|
"ms" <nada (AT) notreally (DOT) net> wrote
| Quote: | I do exactly the same - Just one call to FieldByName for each field at
start-up.
--Which works quite well...except when a given DB column could
translate into different data-types depending on the platform
(e.g., TFloatField vs. TIntegerField with MS-SQL vs. Oracle).
|
To handle that possiblilty, I would use use TField vars to hold the
object references and do appropriate checking where necessary.
I usually add "{Reference Only}" comments to the pointer var
declarations, just to prevent me from getting carried away when
using FreeAndNil() when coding the cleanups. --JohnH |
|
| Back to top |
|
 |
ms Guest
|
Posted: Wed Apr 19, 2006 8:03 pm Post subject: Re: FieldByName |
|
|
| Quote: | I do exactly the same - Just one call to FieldByName for each field at start-up.
|
--Which works quite well...except when a given DB column could
translate into different data-types depending on the platform
(e.g., TFloatField vs. TIntegerField with MS-SQL vs. Oracle). |
|
| Back to top |
|
 |
Les Pawelczyk Guest
|
Posted: Wed Apr 19, 2006 9:03 pm Post subject: Re: FieldByName |
|
|
| Quote: | Aside from your interesting investigation, when my code would
otherwise make lots of FieldByName() lookups, I declare some
variables to hold the pointers to the field objects, load them with
the addresses of the field objects at runtime just ofter opening
the table, and then use them whenever the fields need to be
referenced. --JohnH
|
I have a TParent object that opens the query and for each record it creates the TChild object and calls TChild.Load method passing query as parameter. Creating temp TField variables in TChild makes no sense - they are only read from once. Creating and maintaining them in TParent (up to 50 fields * 15 parent objects) would complicate existing code and future maintenance of it. First - they would have to be passed to TChild.Load method (which is virtual), second - they would have to be maintained every time a new field is added to db table (which happens often enough). Not worth any speed improvement IMO.
Les. |
|
| Back to top |
|
 |
Darryl Strickland Guest
|
Posted: Thu Apr 20, 2006 5:03 am Post subject: Re: FieldByName |
|
|
Les,
I would like to have a look at it to try with several of my applications.
Could you upload it to the attachments group.
Thanks
Darryl Strickland
Les Pawelczyk wrote:
| Quote: | In my quest to speed-up application that loads lots of data from
database during start-up I took a look at TDataSet.FieldByName. It
seems that it eventually finds its way to TFields.FindField which
makes use of AnsiCompareText inside loop which goes through all the
fields. AnsiCompareText calls CompareString which is a Windows API. I
replaced AnsiCompareText with my own ASM version that uses lookup
tables. It seems that FieldByName now executes 30% to 50% faster.
That gives this particular application performance improvement much
greater than what FastMM4 and FastMove can do combined.
Anybody else curious to try it?
Les. |
|
|
| Back to top |
|
 |
Eric Grange Guest
|
Posted: Thu Apr 20, 2006 7:03 am Post subject: Re: FieldByName |
|
|
| Quote: | It seems that FieldByName now executes 30% to 50% faster.
|
I usually just have one FieldByName call per field, after the 'Open', and place
its result in a TField variable that I just use afterward (so no further field
lookup or string searches in the per-record code).
Wasn't there a fast AnsiCompareText challenge discussed sometime ago?
This function is used in a variety of code, could be worth investigating again
in a general context (we already patch it to a faster version @work, though that
was after bumping on performance issues when sorting large listviews/grid-like
components).
Eric |
|
| Back to top |
|
 |
Guest
|
Posted: Thu Apr 20, 2006 10:04 am Post subject: Re: FieldByName |
|
|
This sounds very nice,
would it be possible to share your code so I can try to use it in an
application of mine?
I could also try to look at how to maybe improve it a little more..
Thanks in advance,
(you can mail the code to gekindekop (AT) _NO_SPAMMM_gmail (DOT) com) (offcourse
removing the _NO_SPAMM_) |
|
| Back to top |
|
 |
Carsten Schuette Guest
|
Posted: Thu Apr 20, 2006 11:03 am Post subject: Re: FieldByName |
|
|
Les Pawelczyk wrote:
| Quote: | makes use of AnsiCompareText inside loop which goes through all the
fields. AnsiCompareText calls CompareString which is a Windows API. I
|
You are right. In im opinion it is also a serious bug to call
AnsiCompareText in FieldByName. The field name is usually not
localized, also the strings in "FieldByName" are not localized. So they
should not be compared with "AnsiCompareText", but with "CompareText".
Carsten |
|
| Back to top |
|
 |
Eric Grange Guest
|
Posted: Thu Apr 20, 2006 1:03 pm Post subject: Re: FieldByName |
|
|
| Quote: | The field name is usually not localized
|
If only... I've seen more localized db field names than I would have
desired, with accentuated characters and other strange things in field
or table names, admittedly mostly in "beginner" databases (MSAccess and
MSSQL), but still...
If you honour case-insensitivity for ASCII characters, you have to
honour it for accentuated characters too (among others), which are part
of the locale.
Eric |
|
| Back to top |
|
 |
Les Pawelczyk Guest
|
Posted: Thu Apr 20, 2006 3:03 pm Post subject: Re: FieldByName |
|
|
| Quote: | Could you upload it to the attachments group.
|
I might not be able to do that since some of it was developed on company time, but isn't there FastCode AnsiCompareText? If so, then it could be used as a replacement the same way FastMove replaces System.Move.
Les. |
|
| Back to top |
|
 |
Frederico Pissarra Guest
|
Posted: Sun Apr 23, 2006 9:52 am Post subject: Re: FieldByName |
|
|
"John Herbster" <herb-sci1_at_sbcglobal.net> wrote in message
news:44468765$1 (AT) newsgroups (DOT) borland.com...
| Quote: |
"ms" <nada (AT) notreally (DOT) net> wrote
I do exactly the same - Just one call to FieldByName for each field at
start-up.
--Which works quite well...except when a given DB column could
translate into different data-types depending on the platform
(e.g., TFloatField vs. TIntegerField with MS-SQL vs. Oracle).
To handle that possiblilty, I would use use TField vars to hold the
object references and do appropriate checking where necessary.
I usually add "{Reference Only}" comments to the pointer var
declarations, just to prevent me from getting carried away when
using FreeAndNil() when coding the cleanups. --JohnH
|
I think is cheaper to use Fields property instead searching for a field that
you know the actual relative position on a query:
SELECT A, B, C FROM Table
Fields[0] is Field A, Fields[1] is B...
This way is faster, isn't it?
[]s
Fred |
|
| Back to top |
|
 |
|