From: Jeremy F. <jfi...@ma...> - 2002-10-29 22:51:37
|
Thought this thread might be of interest to others on the list. Nathan = and I have been talking about a couple of issues I've raised, namely, = contentObjects containing collections of other contentObjects and the = performance impact of instantiating so many objects. Note that this reads from the bottom up: Nathan - certainly not wed to the interface. But unless, as you suggest, = the definition of what a field is changes I don't see a way of using = basefield for content objects. Back to the forum example I've been using = - retrieving a collection of threads: The way I suggested: <cfset forum=3D createObject("component","forum").init(forumID)> <cfset threads=3D category.getObjectArray('threads')> <cfloop from=3D"1" to=3D"#arrayLen(thread)#" index=3D"i"> <!--- doing stuff with each thread, like: ---> #thread[i].getField('thread').getValue()#=20 </cfloop> One possible way of doing what you suggest: <cfset forum=3D createObject("component","forum").init(forumID)> <cfset threads=3D category.getField('threads').getValue()> <cfloop from=3D"1" to=3D"#arrayLen(thread)#" index=3D"i"> #thread[i].getField('thread').getValue()# </cfloop> As you can see the only difference is the method call for the threads = array. And of course this gets back to the descriptor for the content = object. In the first case thread would have a property type of = 'objectArray' or 'subcomponent' or something like that, and in the = latter it has the type 'field' with a particular fieldType.=20 If the latter seems cleaner to you, fine. I just did it this way to = avoid reworking basefield - sort of a proof of concept. The developer = using the API already needs to know the 'type' for various fields. Most = are simple strings, but anything that extends basefile will certainly be = handled differently, or at least make several new methods available. So = making 'contentObject' be a possible fieldType should be doable - the = basefieldValue idea is probably the way to go. Let me think about that a = bit. As for the performance issue, it comes in precisely when you want to = instantiate a whole array of contentObjects. If I call load() on a 40 = page book object, a new instance has to be created for each of these = pages. The only way to avoid that is to reference the cached object, = which opens up a whole other can of worms - locking the server scope, = concurrent access to writable data... This may be possible, but is this = a route worth going down. Maybe others have thoughts. - Jeremy ----- Original Message -----=20 From: Nathan Dintenfass=20 To: Jeremy Firsenbaum=20 Sent: Tuesday, October 29, 2002 12:27 PM Subject: RE:=20 Ah, I see what you mean. Yes, get() does that, but only if you wish = to populate from another instance -- which you pass in -- that is, if = you have an existing contentObject that you want to "load()", then you = need to do this. But, in this case you still never need to recreate a = whole new instance as you already have the one you want to load and the = one you retrieve from the cache (except on the first hit) -- but, what = you are saying is that is a performance bottleneck for you, right? Hmm. On the "interface" I was talking about -- yes, the API exposed to the = end user. I figured you were not wed to it. My instinct says that it = would be better to do an overhaul of what a "field" is. First, I'd make = it possible to have an array of values, even if not other contentObject. = Then, I'd work on making it possible to have the value of a field be a = contentObject. Perhaps baseFieldValue.cfc would be one way to get = towards that?? I totally agree that one way or another there needs to be a way to = have a "book" and its "pages" (not to mention many-to-many = relationships) and have "book" and "page" each be instances of a = contentObject. - Nathan -----Original Message----- From: Jeremy Firsenbaum [mailto:jfi...@ma...] Sent: Monday, October 28, 2002 5:33 PM To: na...@ch... Subject: Re:=20 "By the way, the only place I am using the makeClone() is when I put = objects into the cache, not when I take them out of the cache" I'm sorry if I was misleading. "Cloning" takes place going in as = well as coming out, although the makeClone method is only called one = way. Going in, makeclone calls contentObjectPopulateFromInstance, which = does all of the actually duplicating. Coming out, get() calls = contentObjectPopulateFromInstance as well: line 41 from simplefilesystempersister.cfc: if(instance.cache.isObjectCached(arguments.id)){ objectRetrieved =3D instance.cache.getObject(arguments.id); if(structCount(arguments) GT 1) return = contentObjectPopulateFromInstance(arguments[2],objectRetrieved); else return objectRetrieved;=20 } I found the duplicating from a cached instance in = contentObjectPopulateFromInstance to be the bottleneck. "I'm not sure I'm personally satisfied with the interface you are = using in your forums app." I'm all up for criticism - but not sure what you're referring to by = interface. Do you mean the contentObjectArray within basecontentobject, = or the way in which the API is used externally to construct the forum. = Obviously this was just an example I was using to work with the idea of = content objects within content objects. "Are you waiting for a signal from me as to what my alternative = might be?" Well - kinda, yeah. I mean I would like to know if this approach to = "composition" even makes sense, or whether there's another way of doing = "parts of" relationships within modus. Many systems, content management = or otherwise, have this kind of structure. An artifact, say a book, has = many pages, each one of which has been scanned in. At one level, you = want to deal with the book as a whole (when presenting a library of = books), on another level, each one of the pages is a content object unto = itself (so that the book is browsable). I would like to be able to load = the book, for a single request or in session scope, and have the pages = come along for the ride, just as each thread is available within the = forum content object. Does this even make sense within the context of = what modus was and is being designed to do? ----- Original Message -----=20 From: Nathan Dintenfass=20 To: Jeremy Firsenbaum=20 Sent: Monday, October 28, 2002 7:56 PM Subject: RE:=20 Ah, yes. Well, right now you are at the cutting edge of that = question. I'm not sure I'm personally satisfied with the interface you = are using in your forums app. Doesn't feel clean to me, but I have a = hard time justifying that feeling. Are you waiting for a signal from me = as to what my alternative might be? By the way, the only place I am using the makeClone() is when I = put objects into the cache, not when I take them out of the cache -- are = you experiencing serious performance problems with that? My main issue = with performance before the caching was with the getAll(). Load() is = still a bit slower than I'd like, but I figure that will be rarely = called in volume since getAll would be generally be faster. That is an = area to work on, though. - n -----Original Message----- From: Jeremy Firsenbaum [mailto:jfi...@ma...] Sent: Monday, October 28, 2002 4:45 PM To: na...@ch... Subject: Re:=20 Sorry for being obtuse - I mean being able to declare other = content objects as being contained within another content object: forums = are composed of threads, which are composed of posts... ----- Original Message -----=20 From: Nathan Dintenfass=20 To: Jeremy Firsenbaum=20 Sent: Monday, October 28, 2002 7:37 PM Subject: RE:=20 When you say "composition of content object" what do you mean? - n -----Original Message----- From: Jeremy Firsenbaum [mailto:jfi...@ma...] Sent: Monday, October 28, 2002 4:33 PM To: na...@ch... Subject: Re:=20 Fair enough. Maybe it's all of the nested subcomponents that = accounts for the slowness in cloning from the cache. I'd love to do some more work on modus, maybe sink my teeth = in the XML descriptor thing, but I feel like I can't do much with it = until I know whether composition of content objects is feasible. This = seems to be the most important feature needed to model more complex = systems. Looking forward to seeing what you think.=20 -Jeremy ----- Original Message -----=20 From: Nathan Dintenfass=20 To: Jeremy Firsenbaum=20 Sent: Monday, October 28, 2002 7:13 PM Subject: RE:=20 Jeremy: I hadn't yet gotten to look in depth at your changes. I = agree the clone() method is far from optimal (as I mentioned in that = posting). My comment was based on the dramatic performance = enhancement I witnessed on the modustest app after implementing the = caching. My calls to getAll() went from over 400ms with a handful of = "press releases" to 20ms. - n -----Original Message----- From: Jeremy Firsenbaum [mailto:jfi...@ma...] Sent: Monday, October 28, 2002 3:52 PM To: Nathan Dintenfass Subject:=20 Hey Nathan I saw your post to CFCDev today: "I have taken pages that were slow because they had to = instantiate dozens of components and made them very fast by just = grabbing from the cache in the server scope." This got me wondering if you have looked into the = performance issue with clone() that I mentioned last week. It seems like = it wouldn't make a difference whether the subcomponents were = instantiated within the contentObject, as I had tried to do, or if this = were left to the developer to do externally: forums =3D createObject = (forum.cfc), loop for threads =3D createObject(thread.cfc). If you need = "dozens of components" the clone technique doesn't seem to be optimal. Were my performance numbers similar to yours (if you've = had time to look into this) or am I totally off base here? Jeremy |