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.
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,
--