newbie question on treemodel

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
9 messages Options
Reply | Threaded
Open this post in threaded view
|

newbie question on treemodel

thpu
I experienced bad performance using the treemodel for storing data read from
a database with Artists, Albums and cd track information. I tried to build
the tree in pieces and after that setup the main tree, so:

tree1 add: tree2 asChildOf: nil.

But all I got is a view with just the words 'a treemodel' a dozen times,
....

Does anybody have any tips or hints...?

Thanx, ThPu


Reply | Threaded
Open this post in threaded view
|

Re: newbie question on treemodel

Chris Uppal-3
thpu wrote:
> I experienced bad performance using the treemodel for storing data
> read from a database with Artists, Albums and cd track information. I
> tried to build the tree in pieces and after that setup the main tree,
> so:
>
> tree1 add: tree2 asChildOf: nil.
>
> But all I got is a view with just the words 'a treemodel' a dozen
> times, ....

 From the sound of it, you are expecting one TreeModel to be able to be a
"branch" of another TreeModel; that's not a silly thing to think, but it
happens not to be true.

The way the TreeModels work is that they contain an internal data-structure
(the real "tree") and are able to use that to tell the TreeView what nodes
there are and what is a child/parent of what.  So they are not "trees"
themselves, they just hold *hold* a tree, so you can't compose them using
#add:asChildOf:.

You don't say what the performance problems you are seeing are, but if it's
something to do with too many updates as you are building the tree then the
thing to do is to compose the whole tree off-line (as it were), before
connecting it to the Presenter (by setting the #model:).  Otherwise I'm a bit
surprised that you are seeing performance problems with what is presumably a
fairly small tree -- you can't possibly have more than a few thousand CDs can
you ? -- so there may be some other problem with what you are doing.

HTH

    -- chris


Reply | Threaded
Open this post in threaded view
|

Re: newbie question on treemodel

thpu
Hi Chris,

Thanx, this is what I do:
(self readArtists)

do: [:artist | aTree add: (artist at: 'ArtistName') asChildOf: nil.

                 (self readAlbums: (artist at: 'ArtistID'))

                 do: [:album | aTree add: (album at: 'Title') asChildOf:
(artist at: 'ArtistName').

                                    (self readTracks: (album at: 'AlbumID'))

                                    do: [:track | aTree add: (track at:
'Title') asChildOf: (album at: 'Title').]]].

The database connection is pretty fast, there are about 300 artists and
about 500 cd titles with an avarage of 10 tracks. So I thought the
performance issue (about 1 minute) was in searching the right parent nodes
in the tree during insertion (by the way adding the list of artists only is
pretty fast). Building subtrees of albums and tracks and then connect that
subtree in total to the maintree should speed up that process a bit .... I
thought.

After building the tree the presenter is created, is this what you mean by
building the tree offline?

Thanx already, ThPu


"Chris Uppal" <[hidden email]> wrote in message
news:3e19e660$0$157$[hidden email]...

> thpu wrote:
> > I experienced bad performance using the treemodel for storing data
> > read from a database with Artists, Albums and cd track information. I
> > tried to build the tree in pieces and after that setup the main tree,
> > so:
> >
> > tree1 add: tree2 asChildOf: nil.
> >
> > But all I got is a view with just the words 'a treemodel' a dozen
> > times, ....
>
> From the sound of it, you are expecting one TreeModel to be able to be a
> "branch" of another TreeModel; that's not a silly thing to think, but it
> happens not to be true.
>
> The way the TreeModels work is that they contain an internal
data-structure
> (the real "tree") and are able to use that to tell the TreeView what nodes
> there are and what is a child/parent of what.  So they are not "trees"
> themselves, they just hold *hold* a tree, so you can't compose them using
> #add:asChildOf:.
>
> You don't say what the performance problems you are seeing are, but if
it's
> something to do with too many updates as you are building the tree then
the
> thing to do is to compose the whole tree off-line (as it were), before
> connecting it to the Presenter (by setting the #model:).  Otherwise I'm a
bit
> surprised that you are seeing performance problems with what is presumably
a
> fairly small tree -- you can't possibly have more than a few thousand CDs
can
> you ? -- so there may be some other problem with what you are doing.
>
> HTH
>
>     -- chris
>
>


Reply | Threaded
Open this post in threaded view
|

Re: newbie question on treemodel

Chris Uppal-3
thpu,

> The database connection is pretty fast, there are about 300 artists
> and about 500 cd titles with an avarage of 10 tracks. So I thought the
> performance issue (about 1 minute) was [..snipped...]

Wow! You have a very serious undiagnosed performance problem somewhere.  (Or
are you running on an abacus ? ;-)

I tried building a TreeModel with 500 "bands" (represented as Strings of two
random words from a wordlist), each with an average of 1.6 "cds" (represented
as Strings of three random words), each with an average of 10 "titles" (more
Strings of three random words).

(Incidently, I've been enjoying the resultant names -- very '70s.  It's a pity
that Extralinguistic Silversmith only ever released one album; but after
classic tracks like "Hugging tid bona" and "This'll fever Newport", it's hard
to see where they could go next...)

Populating the TreeModel, with no Presenter connected, took about 1/2 second
(on this 650Mz P3), of which about half was just generating the random strings.
Connecting the model to a TreePresenter before populating it made the process
go up to about a second.

So you are loosing about a minute somewhere that you shouldn't.

First thing to try is check the database stuff.  Comment out the
#add:asChildOf: calls (but still fetch the same data from the database in the
same order), does it still take more than a second or two to run ?  If so then
the database -- or more likely the way you are using it -- is the problem.

Next (if it isn't the DB) thing is get hold of Ian Bartholomew's "Profile
Browser" (from http://www.idb.me.uk/goodies.html).  That'll tell you quickly
where the time is going.  And much more easily than sitting scratching your
head, trying to work out what'll make a difference ;-)

> After building the tree the presenter is created, is this what you
> mean by building the tree offline?

Well, either that or create and populate the Model before telling the Presenter
about it:

    presenter := ...
    tree := self makeAndPopulateTree.
    presenter model: tree.

But, as I mentioned, there isn't much of a performance difference, so it's
probably not worth your while unless you find it makes the GUI look better.

Good luck!  Post again if you get stuck.

    -- chris


P.S.

    Horse Amnesia.
    Infra Sit.
    Passerby Vitrio.

I could go on and on...


Reply | Threaded
Open this post in threaded view
|

Re: newbie question on treemodel

Ian Bartholomew-18
Chris Uppal wrote:

> First thing to try is check the database stuff.  Comment out the
> #add:asChildOf: calls (but still fetch the same data from the database in
> the same order), does it still take more than a second or two to run ?
> If so then the database -- or more likely the way you are using it -- is
> the problem.

Another way of proving that might be to reduce the db calls by caching some
of the information to prevent multiple db accesses on the same field.

self readArtists do: [:artist | | artistName |
    artistName := artist at: 'ArtistName'.
    aTree add: artistName copy asChildOf: nil.
    (self readAlbums: (artist at: 'ArtistID')) do: [:album | | albumTitle |
        albumTitle := album at: 'Title'
        aTree add: albumTitle copy asChildOf: artistName.
        (self readTracks: (album at: 'AlbumID')) do: [:track |
            aTree add: (track at: 'Title') asChildOf: albumTitle]]].

If the db accessing is the problem (and it does look like it) then the above
ought to show an decrease in execution time.

thpu
I've added the extra #copy as there can be a problem with adding
identical strings in these simple trees - for example ...

a := 'aaa'.
b := 'bbb'.
c := 'ccc'.
t := TreeModel new.
t add: a asChildOf: nil.
t add: b asChildOf: nil.
t add: c asChildOf: a.
t add: c asChildOf: b.
TreePresenter showOn: t

... doesn't work as expected (and gets even worse if you use literal strings
in the code and don't evaluate them all together).  Something to be aware
of.

--
Ian Bartholomew


Reply | Threaded
Open this post in threaded view
|

Re: newbie question on treemodel

thpu
In reply to this post by thpu
Chris, Ian,

Thanx for the tips, I did some statistics:
- the total elapsed time is about 48 sec avarage
- there are 946 database reads with an avarage time of 40 ms (including a
conversion of a DBresultset into an array)
- so this covers for about 38 sec of the 48 sec
- there are 8303 tree inserts and they take the rest of the time so 10 sec
(about 1 ms per insert).

So indeed it's not in the treemodel!

Thanx, again Theo

"thpu" <[hidden email]> wrote in message
news:avcmdu$61n$[hidden email]...
> I experienced bad performance using the treemodel for storing data read
from

> a database with Artists, Albums and cd track information. I tried to build
> the tree in pieces and after that setup the main tree, so:
>
> tree1 add: tree2 asChildOf: nil.
>
> But all I got is a view with just the words 'a treemodel' a dozen times,
> ....
>
> Does anybody have any tips or hints...?
>
> Thanx, ThPu
>
>


Reply | Threaded
Open this post in threaded view
|

Re: newbie question on treemodel

Christopher J. Demers
"thpu" <[hidden email]> wrote in message
news:avfdag$qoe$[hidden email]...
> Chris, Ian,
>
> Thanx for the tips, I did some statistics:
> - the total elapsed time is about 48 sec avarage
> - there are 946 database reads with an avarage time of 40 ms (including a
> conversion of a DBresultset into an array)
> - so this covers for about 38 sec of the 48 sec

You might consider using precompiled statements if you are not already doing
so.  It has been a while, but I can remember one case where using
precompiled statements led to massive speed improvement.  It was a big
improvement, to the extent that the application was almost unusable without
precompilation but was quite quick with it.

For more information see the Dolphin docs here:
http://www.object-arts.com/Lib/EducationCentre4/htm/preparingsqlforlaterexec
ution.htm

These days I use a commercial add-on tool for Dolphin called ReStore (
http://www.solutionsoft.co.uk/restore/ ) for my database work.  It handles
relational to object mapping, and statement precompilation and caching.  It
is easy to use and quite powerful.

Chris


Reply | Threaded
Open this post in threaded view
|

Re: newbie question on treemodel

Chris Uppal-3
In reply to this post by thpu
thpu,

> - there are 946 database reads with an avarage time of 40 ms
> (including a conversion of a DBresultset into an array)

Hmm, that's way too high.  If you mean that you are doing 946 DB *queries*,
then that's your problem.  A time of 40ms per query doesn't sound too bad, but
946 queries to build a simple tree is many more than I think you need.  I'd
expect you to be able to populate the tree with at most 3 queries -- something
like:

(This a mixture of SQL and Smalltalk -- don't expect it to run!)

tree := TreeModel withRoots: #() searchPolicy: SearchPolicy equality).
(select ARTIST_NAME from ARTISTS) do:
    [:artist | tree add: (Artist name: artist) asChildOf: nil].
(select CD_NAME, ARTIST_NAME from CDS) do:
    [:cd :artist | tree add: (CD name: cd) asChildOf: (Artist name: artist)].
(select TRACK, CD_NAME from TRACKS) do:
    [:track :cd | tree add: (Track name: track) asChildOf: (CD name: cd)].

That's assuming a DB layout with 3 tables, ARTISTS, CDS, and TRACKS.  Other
layouts would be perfectly sensible (and quite possibly better), so the details
of the SQL used to pull the data our would obviously change.  You could even
cut it down to one SQL query (perhaps using a join), but at the cost of
slightly more complexity in the Smalltalk code.  I doubt if it's worth it in
this case.

Still going on my assumption that you are doing 946 DB queries (and I apologise
if the assumption's wrong), then a word of advice: When you're using a SQL
database, you have to do things *its* way.  The natural way that you'd write OO
code talking to a bunch of objects, asking them for data as and when you need
it, doesn't work.  SQL databases expect to be asked for all the data you are
going to want upfront and in big gobs and, if you don't do it their way, then
your code is going to run a few orders of magnitude slower than it could.

BTW, Ian's message about the kind of comparisons used in TreeModel reminded me
that they default to identity comparison (they use #== to find if an object's
already in the tree).  I thought I'd make my example illustrate how to create a
TreeModel that uses equality comparison instead.  Note that TreeModels require
that each object appears only *once* (as determined by the kind of comparison
you use).  E.g. if I created a TreeModel that used case-insensitive String
comparison:
    TreeModel withRoots: #() searchPolicy: SearchPolicy caseInsensitive.
then I could not have 'Dog' and 'dog' appearing in two difference places in the
tree.

> - there are 8303 tree inserts and they take the rest of the time so
> 10 sec (about 1 ms per insert).


Hmm, that seems an order of magnitude too high too.  It's not your main
bottleneck, though, so it's probably not worth bothering with for performance
reasons unless/until you speed up the DB code (assuming you want to).  However
it *may* indicate a problem of some sort that hasn't yet shown up as an actual
bug.  As I've mentioned, Ian's Profile Browser is the diagnostic tool of choice
here.

    -- chris


Reply | Threaded
Open this post in threaded view
|

Re: newbie question on treemodel

thpu
In reply to this post by thpu
Hi all,

Thanx for all the input, tried a lot of alternatives, but the one with the
major impact was:

-> preparing the SQL statements in advance and using the query exec:
construction.

The total time dropped from 48 to 8 sec.

Theo.

"thpu" <[hidden email]> wrote in message
news:avcmdu$61n$[hidden email]...
> I experienced bad performance using the treemodel for storing data read
from

> a database with Artists, Albums and cd track information. I tried to build
> the tree in pieces and after that setup the main tree, so:
>
> tree1 add: tree2 asChildOf: nil.
>
> But all I got is a view with just the words 'a treemodel' a dozen times,
> ....
>
> Does anybody have any tips or hints...?
>
> Thanx, ThPu
>
>