[Glass] Lesson Learned: don't use #collect: for RcIdentityBag

Mariano Martinez Peck via Glass glass at lists.gemtalksystems.com
Thu Dec 3 05:41:56 PST 2015


As you know, if you want a collection to store a list of domain objects
that support both, Reduced Conflicts behavior and indexes, your only option
is RcIdentityBag. So I think there are many out there like me using this
collection.

I was just doing some code like this:

getSF1AllKnownTickers
"Ansers a list with all the known tickers of the database SF1"
| tickers securities |
securities := self getSF1AllKnownSecurities.
tickers := OrderedCollection new: securities size.
tickers addAll: (securities collect: [ :each | each ticker ]).
tickers addAll: (securities collect: [ :each | each tickerOld ]).
^ tickers asSet

The #size of 'securities' instVar was around 8k elements. Guess how long
#timeToRun took?
12 seconds!!! I was doing an web autocomplete with this result...so imagine
it was TOO slow.

The reason is that #getSF1AllKnownSecurities does the query to the DB, and
the result is a RcIdentityBag. #collect: will use the same class of the
receiver in order to generate the new collection. And you know, RC classes
bring some overhead..even more then adding objects.
And in this case, it was completely useless for me to have a RC collection
there since it was a temporal variable used for displaying an autocomplete.

Rewriting the above method to this (basically avoid the #collect:)

getSF1AllKnownTickers
  "Ansers a list with all the known tickers of the database SF1"

  | tickers securities |
  securities := self getSF1AllKnownSecurities.
  tickers := OrderedCollection new: securities size.
  securities do: [ :each | tickers add: each ticker ].
  securities do: [ :each | tickers add: each oldTicker ].
  ^ tickers asSet

Took 50ms... 240x faster? ..

Now I am wonder what path to do:

1) Check every single #collect: I might be sending to RcIdentityBag
instances (basically every result of a query of stored domain objects) and
see if I can avoid it.

2) Fortunately, I have a common API to query the stored domain objects. So
I could modify the code that does the query and directly answer  a
IdentityBag for example, rather than a RcIdentityBag. Note that the API for
STORING objects use another method.. so the method for querying is just for
querying. And anyway, the API for storing  receives objects.. not the
collection of the objects.

I may be paying this #asIdentityBag cost for every query..but I avoid
having to change all possible usage of #collect:

*From what I can see #asIdentityBag seems quite fast for RcIdentityBag and
it will be the collection with less side effects for my case. So I guess I
will follow this path. *

Do any of you have a similar problem? How do you handle this?

Cheers,

-- 
Mariano
http://marianopeck.wordpress.com
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.gemtalksystems.com/mailman/private/glass/attachments/20151203/f50730f1/attachment.html>


More information about the Glass mailing list