18 Replies Latest reply on Oct 30, 2007 4:52 AM by obouillaud

    cfc generation is slow

    obouillaud Level 1
      Hi

      Here is my problem :
      as soon as I create a cfc, it takes a lot of time (on a computer time scale).
      I'm running CF8 but it was the same thing on CF7

      Here is a simple test (see code attached).
      On my server it takes between 170 and 200 ms for each loop of hundred cfc generations.
      That is around 16ms for each CFC... where is the error ??? Sometimes Google takes less time to generate a whole web page ;-)
      As soon as I need inheritance or imbricated cfc's for example to display a small list of 5 products on a page, it takes 150-400 ms to generate !!!

      Do you have the same behavior ?
        • 1. Re: cfc generation is slow
          Charlie Griefer Level 1
          component instantiation has always been an expensive process, and not well-suited for doing within a loop.

          can't you instantiate it once, then do the assignment inside the loop?

          <cfset myComponent = createObject('component', 'com.produits.test') />
          <cfloop index="i" ... ><cfset "myVar#i#" = myComponent /></cfloop>

          ?
          • 2. Re: cfc generation is slow
            Level 7
            Which version of CF?

            --
            Adam
            • 3. Re: cfc generation is slow
              Grizzly9279 Level 1
              This was a known issue with CF7 at least; rumor has it CF8 was supposed to speed up object instantiation (among other things). Your mileage may vary though.

              Like CJ suggested, you may need to re-design your approach to account for performance limitations in this programming environment.

              I've gone so far as to implement an "object recycling" mechanism in the past so I could re-use old, discarded CFCs objects, since it was many times faster to do that than to create brand new CFC instances every time.

              Like anything, there's more than one way to skin a cat. Sometimes you have to get creative to get the desired result. I know that's not the answer you were looking for, but at least you know that you're not alone in this :)
              • 4. cfc generation is slow
                obouillaud Level 1
                [CJ] : your suggestion is very interresting, that's why I love forums, you can pass 3 days looking for a solution and someone totaly outside of the project finds a solution in a few minutes !

                ... too bad in the case I have, it's not possible as the instancied object varies. I have a "product" abstract object which is overridden by some "book", "software", ... objects. As I have betwen 10 and 20 different "flavours" of objects, even if I can instanciate them just one time (which is better than on each row), I will still have 10 to 20 x 16ms per page... which is still slow.

                I'm working on a caching mechanism to store the objects in the Application scope, it looks promising.

                EDIT : Hum in fact CJ, I'm not sure of your solution... in my case... in each loop I create the object, I set different properties and then I add it in a struct. So at the end on the loop I have a struct of differents obects (books, softwares, ...). If I try your solution, at the end I have a struct of objects which all refers to the same object, with same properties. I naively though that a
                <cfif isdefined("fresh_#product_type#") is false >
                <cfset "fresh_#product_type#" = CreateObject("component","composants.produits.#product_type#")>
                </cfif>
                followed by
                <cfset my_product = evaluate("fresh_#product_type#")>
                would duplicate the object, not create a reference to it...
                • 5. Re: cfc generation is slow
                  Grizzly9279 Level 1
                  CF7 cannot create "copies" of CFCs unfortunately. I can't speak for CF8 though. CF8 was supposed to add support for object serialization however; this leads to me believe that it should be possible in CF8 to "copy" an object, if only by a serialization and de-serialization process.

                  So in other words, applying the assignment operator to a CFC will always result in a pass-by-reference assignment (a pointer). And no, the duplicate() function does not work as you hope it would against CFCs :)

                  Best of luck.
                  • 6. Re: cfc generation is slow
                    cf_dev2 Level 1
                    > at the end I have a struct of objects which all refers to the same object, with same properties.

                    Yes, its important to understand that CF passes most complex objects (structures, queries, cfcs, ..) by reference. You can use Duplicate() on some objects to obtain an independent copy. But as Grizzly9279 mentioned, cfc's are not one of them
                    http://livedocs.adobe.com/coldfusion/7/htmldocs/00001008.htm


                    • 7. cfc generation is slow
                      obouillaud Level 1
                      Ok... I didn't test but I'm quite sure that serialization + duplication + "unserialiszation" is slower than a new CreateObject.

                      I tried my Application scope cache... and if it seems perfect on my dev server, it seems a bad idea on my production server.
                      The structure in the Application scope rise from a few KB to 10 MB, 15 MB everything seems fine... but after a while the server becomes very slow, unresponsive... with average response time higher than 60 seconds... and I have to restart the server.

                      Too bad that the caching solution seems worse than the "slow solution"
                      • 8. Re: cfc generation is slow
                        Level 7
                        > Ok... I didn't test but I'm quite sure that serialization + duplication +
                        > "unserialiszation" is slower than a new CreateObject.

                        Eek, yes.

                        Did you ever answer my question as to which CF version, btw?

                        One thing you could look at is - and this is a bit of a cop-out, I agree -
                        is to store the member variables of the object in a cache (so that's just a
                        struct), and use the (cached) CFC instance as a factory sort of
                        arrangement. When you need to do any operations on the object, pass the
                        cached struct in as one of the arguments of the method you're calling. Not
                        very object-oriented, no, but CF ain't OO. Plus it has trouble
                        instantiating objects, so one has to work around this.

                        --
                        Adam
                        • 9. Re: cfc generation is slow
                          obouillaud Level 1
                          Adam : in my first post is written "I'm running CF8 but it was the same thing on CF7"... That should answer your question :-)

                          Your suggestion makes me think that in fact it would probably be a better idea to avoid CFC usage. Maybe just cfm pages with includes and functions should be far more efficient !


                          • 10. Re: cfc generation is slow
                            Level 7
                            > Adam : in my first post is written "I'm running CF8 but it was the same thing
                            > on CF7"... That should answer your question :-)

                            Did you edit the post to include that after the fact? I'm reading from the
                            NNTP feed, and that's not in your first post that I'm looking at.

                            Either way, sorry for the "silly" question.

                            I was hoping you were foing to say "CFMX6.0", or something, which was a
                            known dog at instantiating CFCs. CF8's a lot better.


                            > Your suggestion makes me think that in fact it would probably be a better idea
                            > to avoid CFC usage. Maybe just cfm pages with includes and functions should be
                            > far more efficient !

                            Yeah, they can be a bit of a pain in the butt performance-wise. It depends
                            on the situation. They're fine for stateless factory type things, or as
                            "bags o' functions", but not much chop as "real" objects, if one's app is
                            going to rely heavily on them.

                            One thing I think of when I'm looking at your code (which I realise is just
                            an example,but infer it's related to your real situation) though: you're
                            basically generating a collection of products in your loop. So why don't
                            you create ONE collection class, which loads its data from [whatever
                            mechanism your individual products are loaded via]. I guess it depends on
                            whether you're dealing with the collection or with one-off products more
                            often. The collection class could still have a getProduct(sku=something)
                            method.

                            --
                            Adam
                            • 11. Re: cfc generation is slow
                              obouillaud Level 1
                              I edited my first post a few minutes after its initial post... I can't remember why, but I guess it was to add the CF8/CF7 fact... I didn't knew that the newsgroup didn't reflect the changes of the posts. Sorry.

                              I already use a collection... but it's a collection of "product" objects... ;-(
                              • 12. Re: cfc generation is slow
                                Level 7
                                > I already use a collection... but it's a collection of "product" objects... ;-(

                                Sure: I'm imagining it's this collection you sample code came from, this
                                being the case. Which would be fine if that notion worked.

                                What I'm suggesting is not make a "collection of objects"; make a class
                                that is "ObjectCollection", and don't deal with the individual items as
                                objects; deal with ONE object which works @ collection-level, not
                                object-level.

                                --
                                Adam
                                • 13. Re: cfc generation is slow
                                  obouillaud Level 1
                                  I understand. and I should store the properties of my products in a struct ?
                                  And the methods within the ObjectCollection cfc ?

                                  for example I have a "set_price(float price ,bool with_taxes)" method in my product object. It set both the price with taxes and without taxes (that's an example). So in your suggestion I should rewrite this method with something like :
                                  set_price(float price ,bool with_taxes, struct table_of_products,int product_id) which means pass the struct of my products and the id of the product I want to se the price ?
                                  • 14. Re: cfc generation is slow
                                    Level 7
                                    > I understand. and I should store the properties of my products in a struct ?
                                    > And the methods within the ObjectCollection cfc ?

                                    Yep.

                                    Note: this is only a suggestion, and something to mull over. I've given it
                                    as much thought as it has taken me to type in.


                                    > set_price(float price ,bool with_taxes, struct table_of_products,

                                    Well the struct would be one of the member variables of the object, so
                                    there's probably no reason to pass it in to the method. It's "safe" to
                                    reference member variables directly.

                                    My suggestion of having an external struct holding the data was back when
                                    we were discussing having the Product CFC instance as a "bag o' functions"
                                    relating to a product struct - which would accordingly only need to be
                                    created once, as opposed to a discrete object for each product.

                                    If you're just having the one object for the ProductCollection, then the
                                    data should remain in the object.

                                    --
                                    Adam
                                    • 15. Re: cfc generation is slow
                                      obouillaud Level 1
                                      That's really lots of work, just to bypass Coldfusion flaws !
                                      They said since CFMX that it's an object oriented language. Everybody is writing about inheritance, design patterns, ... and when you use it... you end up with a slow application, which also seems the cause of server instabilities (cpu/memory intensive) !

                                      Sometimes I think about my firsts CF pages, with includes, and query + output directly in the cfm file... not very good for reusability... but the performances were never a problem !
                                      • 16. Re: cfc generation is slow
                                        Level 7
                                        > That's really lots of work, just to bypass Coldfusion flaws !

                                        Sure.


                                        > They said since CFMX that it's an object oriented language.

                                        No-one that knows what they're talking about has ever claimed that.

                                        It's got some object-oriented touches to it. It ain't OO, and Macromedia /
                                        Adobe have never claimed as much.


                                        To be honest, we've had the problems you're seeing in the past, but not for
                                        a couple of years. And we use CFCs fairly extensively. Sometimes stuff
                                        needs coding around or to be factored in a different way, but as long as
                                        one doesn't get too dogmatic about things, there's no probs with that.

                                        --
                                        Adam
                                        • 17. Re: cfc generation is slow
                                          rupesh_kumar Adobe Employee
                                          obouillaud,
                                          CF8 is much faster than CF7 when it comes to cfc creation. Running your code, my laptop (which is very slow) takes 100 ms for each of iteration. And since you are creating 100 objects in each iteration, thats nearly 1 ms for each CFC which is not that bad. Is it? On a better server machine this time will be much smaller.
                                          You can make it even faster by enabling trusted cache.

                                          Regarding cfc, Duplicate does support cfc in CF8. And I think there is some misconception regarding cfc serialization and duplicate. You do not need to worry about serialization and deserialization. All you do is to call Duplicate. But that time will be more or less same as cfc instantiation time.
                                          • 18. cfc generation is slow
                                            obouillaud Level 1
                                            you know what ? I made a miscalculation... 170 ms fo 100 iterations... thats 1.7 ms by iteration, not 17 ms !
                                            That said, I think in fact that's file-system related as when I test on my prouction servers (with files stored on an external NAS), a 100 iterations loop takes between 700 and 1500 ms to complete...

                                            And the problem is also more important as soon as you use inheritance.

                                            As soon as I enable trusted cache the performances are awesome !!!
                                            I will give trusted cache a try...