House of Fusion
Search over 2,500 ColdFusion resources here
  
Home of the ColdFusion Community

Mailing Lists
Home /  Groups /  ColdFusion Talk (CF-Talk)

query passed by value from a udf?

  << Previous Post |  RSS |  Sort Oldest First |  Sort Latest First |  Subscribe to this Group Next >> 
Dave,
Michael Dinowitz
03/09/10 10:26 P
Now that is a very profound way of putting it.
Michael Dinowitz
03/10/10 12:37 A
Hm. I used this without any real results:
Michael Dinowitz
03/10/10 12:55 A
You can circumvent this using duplicate( )
Mark A. Kruger
03/09/10 10:27 P
Very true
Mark A. Kruger
03/09/10 10:45 P
Top  |   Reply  |   Original Post  |   RSS Feed  |   Subscribe to this Group
Author:
Michael Dinowitz
03/09/2010 09:49 PM

Here's another useless question. When the following UDF is invoked, it will return a query. Inside the UDF, the query is being assigned to the local scope so theoretically it should 'die' when the UDF is finished running. But it's returning a complex datatype, which should be passed by reference. Is the query being returned passed by reference or by value. I'm assuming value because the reference should 'die' with the UDF. <cffunction name="test" returntype="any">   <cfquery name="local.manga" datasource="mangadb">     select top 1 *     from titles   </cfquery>     <cfreturn manga> </cffunction> -- Michael Dinowitz

Top  |   Parent  |   Reply  |   Original Post  |   RSS Feed  |   Subscribe to this Group
Author:
Dave Watts
03/09/2010 10:01 PM

----- Excess quoted text cut - see Original Post for more ----- Queries are always, ALWAYS, passed by reference, no matter what you're passing them into or out of. Let's assume you have a line below the function: <cfset myquery = test()> In this case, there are two references that point to the same object, assuming that you're calling the function and returning the value into a variable of your own. But there's only one object. The reference inside the function (local.manga) will go out of scope when the function exits, but the object corresponding to that reference will only go out of scope when the variable myquery itself goes out of scope. Dave Watts, CTO, Fig Leaf Software http://www.figleaf.com/ http://training.figleaf.com/ Fig Leaf Software is a Veteran-Owned Small Business (VOSB) on GSA Schedule, and provides the highest caliber vendor-authorized instruction at our training

Top  |   Parent  |   Reply  |   Original Post  |   RSS Feed  |   Subscribe to this Group
Author:
Michael Dinowitz
03/09/2010 10:26 PM

Dave, The way you make it sound, the instance of the UDF that is run stays in memory as long as there is a reference to the query that it contains. If I expanded the example to say that the UDF was a method of some component and was being called with a cfinvoke, the same case would apply. The component instance will stay in memory as long as a reference to the query exists, even though the query should be local to the UDF and nothing should be returned from the UDF. You also use the term "go out of scope" which I take to mean "can no longer be accessed, but still exists in memory". I assume this is linked to my other question about the memory used by invoked components being reused or not. If the memory is not reused, the component stays in memory but is no longer accessible ('out of scope') Rather useless questions, but... Thanks. :) -- Michael Dinowitz ----- Excess quoted text cut - see Original Post for more -----

Top  |   Parent  |   Reply  |   Original Post  |   RSS Feed  |   Subscribe to this Group
Author:
Dave Watts
03/09/2010 10:36 PM

> The way you make it sound, the instance of the UDF that is run stays > in memory as long as there is a reference to the query that it > contains. No, the instance itself - the variable that corresponds to the function itself - need not stay in memory. It will go out of scope right after it runs, and will be eligible for garbage collection. But the query that was created by that function will remain in memory until all references to that query no longer exist. > If I expanded the example to say that the UDF was a method of some > component and was being called with a cfinvoke, the same case would > apply. The component instance will stay in memory as long as a > reference to the query exists, even though the query should be local > to the UDF and nothing should be returned from the UDF. No, again, the queries created by a method of a CFC don't depend on the CFC's continued existence, as long as other references to those queries now exist. This may be a bit counterintuitive, but the useful thing to understand here is the difference between the stack and the heap. References exist on the stack; the objects being referenced exist in the heap. > You also use the term "go out of scope" which I take to mean "can no > longer be accessed, but still exists in memory". I assume this is > linked to my other question about the memory used by invoked > components being reused or not. If the memory is not reused, the > component stays in memory but is no longer accessible ('out of scope') Right. Once a variable name ("reference") goes out of scope, I can't refer to the object to which that reference points unless there's another reference pointing to the same object. Dave Watts, CTO, Fig Leaf Software http://www.figleaf.com/ http://training.figleaf.com/ Fig Leaf Software is a Veteran-Owned Small Business (VOSB) on GSA Schedule, and provides the highest caliber vendor-authorized instruction at our training centers, online, or onsite.

Top  |   Parent  |   Reply  |   Original Post  |   RSS Feed  |   Subscribe to this Group
Author:
Michael Dinowitz
03/09/2010 10:54 PM

> No, the instance itself - the variable that corresponds to the > function itself - need not stay in memory. It will go out of scope > right after it runs, and will be eligible for garbage collection. But > the query that was created by that function will remain in memory > until all references to that query no longer exist. But we're talking about a single request so if there is no garbage collection during a requests lifetime, being eligible or not makes no difference. Be that as it may, you're saying that the fact that a reference to the query is still in use, the query 'jumps' out of the UDF's local scope to live on in the requests memory. > thing to understand here is the difference between the stack and the > heap. References exist on the stack; the objects being referenced > exist in the heap. Can you expand a bit on what you're saying here? Thanks

Top  |   Parent  |   Reply  |   Original Post  |   RSS Feed  |   Subscribe to this Group
Author:
Dave Watts
03/09/2010 11:07 PM

> But we're talking about a single request so if there is no garbage > collection during a requests lifetime, being eligible or not makes no > difference. Right, but you could be storing the reference you create for a lot longer than a single page request. > Be that as it may, you're saying that the fact that a reference to the > query is still in use, the query 'jumps' out of the UDF's local scope > to live on in the requests memory. The query itself, as an object on the heap, is never actually in the function's local scope. Objects on the heap don't really have a scope. References do, and the reference to that query that's declared in the function's will be marked for deletion when the function finishes. The query object itself will be marked for deletion when there are no more references pointing to it. > > References exist on the stack; the objects being referenced > > exist in the heap. > > Can you expand a bit on what you're saying here? Sure. If you create a query: <cfquery name="foo" ...> ... </cfquery> what's actually happening there is that you've created two things - the query itself, which is just an object with some stuff in it, and a reference to that object, "foo". So, then you do something like this: <cfset bar = foo> Now, you still have one query object, but two references to that object: foo and bar. Next, you do something like this: <cfset structDelete(variables, "foo")> Now, you still have the original query object, but only one reference to it: bar. Since all this is happening in the span of a single page request, it won't likely make any difference in memory consumption, but you could just as easily create references in the Session, Application or Server scopes and things would work the same way. This concept of references on the stack vs objects in the heap is common in many modern languages. Here's a description from the "Java for ColdFusion Developers" book that came out a few years ago: http://www.informit.com/articles/article.aspx?p=31755&seqNum=8 Dave Watts, CTO, Fig Leaf Software http://www.figleaf.com/ http://training.figleaf.com/ Fig Leaf Software is a Veteran-Owned Small Business (VOSB) on GSA Schedule, and provides the highest caliber vendor-authorized instruction at our training centers, online, or onsite.

Top  |   Parent  |   Reply  |   Original Post  |   RSS Feed  |   Subscribe to this Group
Author:
Michael Dinowitz
03/10/2010 12:37 AM

Now that is a very profound way of putting it. Well, this deals with the issues I had with how cfinvoke and other tags were described as working. Now I just have to say it right. Fun. :) So the question now is if GC can be called programatically after all references to a large 'object' is removed during a single request. That'll have to be for another time when I don't have a chapter to finish. :) ----- Excess quoted text cut - see Original Post for more -----

Top  |   Parent  |   Reply  |   Original Post  |   RSS Feed  |   Subscribe to this Group
Author:
Brad Wood
03/10/2010 12:48 AM

> So the question now is if GC can be called programatically after all > references to a large 'object' is removed during a single request. Yes. <cfset obj = CreateObject("java", "java.lang.System")> <cfset result = obj.gc()> Careful though-- Garbage Collection can be an expensive operation.  Also, GC can be a little complicated.  Just because you run the code above may not guaruntee everything you expect to be collected will be. ~Brad

Top  |   Parent  |   Reply  |   Original Post  |   RSS Feed  |   Subscribe to this Group
Author:
Michael Dinowitz
03/10/2010 12:55 AM

Hm. I used this without any real results:   <cfset runtime = CreateObject("java","java.lang.Runtime").getRuntime()>   <cfset runtime.gc()> I'll have to try java.lang.System once my comic bot is done it's nights work. Don't want to interrupt a 'real' operation for an experiment that'll just distract me from what I'm supposed to be doing. :) -- Michael Dinowitz ----- Excess quoted text cut - see Original Post for more -----

Top  |   Parent  |   Reply  |   Original Post  |   RSS Feed  |   Subscribe to this Group
Author:
Dave Watts
03/10/2010 12:53 AM

> So the question now is if GC can be called programatically after all > references to a large 'object' is removed during a single request. While Brad points out that this is possible, I don't know if objects are actually marked for deletion until the request has finished. In addition, it's the kind of thing that you really don't want to get into - if you want to manage memory directly, that's why we have C/C++. The thrust of modern languages like Java is that memory management should be something that the computer does, rather than the programmer. Dave Watts, CTO, Fig Leaf Software http://www.figleaf.com/ http://training.figleaf.com/ Fig Leaf Software is a Veteran-Owned Small Business (VOSB) on GSA Schedule, and provides the highest caliber vendor-authorized instruction at our training centers, online, or onsite.

Top  |   Parent  |   Reply  |   Original Post  |   RSS Feed  |   Subscribe to this Group
Author:
Brad Wood
03/10/2010 12:59 AM

This is starting to sound like one of those "Hibernate knows best" sort of discussions.  lol A sentiment I generally agree with, mind you.  Second guessing Java's GC logic is probably for pretty darn special scenarios. ~Brad ----- Excess quoted text cut - see Original Post for more -----

Top  |   Parent  |   Reply  |   Original Post  |   RSS Feed  |   Subscribe to this Group
Author:
Michael Dinowitz
03/10/2010 01:17 AM

It's not something I would actually use but as long as we've meandered over to it, I might was well ask it. :) Philosophically, I'm against people being able to call GC from within a request. Programmatic GC might promote the bad habit of depending on it over cleaner and tighter applications. If I see a request is taking up more memory than it logically should then my first place to look is the code, not the java. -- Michael Dinowitz ----- Excess quoted text cut - see Original Post for more -----

Top  |   Parent  |   Reply  |   Original Post  |   RSS Feed  |   Subscribe to this Group
Author:
Mark A. Kruger
03/09/2010 10:27 PM

You can circumvent this using duplicate( ) <cfset test = duplicate(test())/> Which makes a deep copy of the object by value. ----- Excess quoted text cut - see Original Post for more ----- Queries are always, ALWAYS, passed by reference, no matter what you're passing them into or out of. Let's assume you have a line below the function: <cfset myquery = test()> In this case, there are two references that point to the same object, assuming that you're calling the function and returning the value into a variable of your own. But there's only one object. The reference inside the function (local.manga) will go out of scope when the function exits, but the object corresponding to that reference will only go out of scope when the variable myquery itself goes out of scope. Dave Watts, CTO, Fig Leaf Software http://www.figleaf.com/ http://training.figleaf.com/ Fig Leaf Software is a Veteran-Owned Small Business (VOSB) on GSA Schedule, and provides the highest caliber vendor-authorized instruction at our training

Top  |   Parent  |   Reply  |   Original Post  |   RSS Feed  |   Subscribe to this Group
Author:
Michael Dinowitz
03/09/2010 10:37 PM

It's not a question of circumvention, just of understanding how things operate under the covers. If a statement is made in the docs that "any variables local to a UDF are destroyed when the UDF is exited", where does it leave things like the query in my example. Either it is not destroyed, and a reference to the query is passed or it is destroyed and a copy (ala the duplicate() function) is passed. Dave holds by the former. Unless I hear from someone who's gone deeper into ColdFusion's internal memory management, I'm going to assume Dave is basically right. How about Railo? Gert, want to chime in? Thanks -- Michael Dinowitz > > You can circumvent this using duplicate( ) > > <cfset test = duplicate(test())/> > > Which makes a deep copy of the object by value.

Top  |   Parent  |   Reply  |   Original Post  |   RSS Feed  |   Subscribe to this Group
Author:
Mark A. Kruger
03/09/2010 10:41 PM

Yes ... I jumped in late without paying attention Michael. I'm tracking now :)   Mark A. Kruger, MCSE, CFG (402) 408-3733 ext 105 www.cfwebtools.com www.coldfusionmuse.com www.necfug.com It's not a question of circumvention, just of understanding how things operate under the covers. If a statement is made in the docs that "any variables local to a UDF are destroyed when the UDF is exited", where does it leave things like the query in my example. Either it is not destroyed, and a reference to the query is passed or it is destroyed and a copy (ala the duplicate() function) is passed. Dave holds by the former. Unless I hear from someone who's gone deeper into ColdFusion's internal memory management, I'm going to assume Dave is basically right. How about Railo? Gert, want to chime in? Thanks -- Michael Dinowitz > > You can circumvent this using duplicate( ) > > <cfset test = duplicate(test())/> > > Which makes a deep copy of the object by value.

Top  |   Parent  |   Reply  |   Original Post  |   RSS Feed  |   Subscribe to this Group
Author:
Dave Watts
03/09/2010 10:50 PM

> It's not a question of circumvention, just of understanding how things > operate under the covers. If a statement is made in the docs that "any > variables local to a UDF are destroyed when the UDF is exited", where > does it leave things like the query in my example. Either it is not > destroyed, and a reference to the query is passed or it is destroyed > and a copy (ala the duplicate() function) is passed. Dave holds by the > former. Well, the answer to that question depends on how you define "variable". From the perspective of the programmer, the variable is destroyed - I can't reference it any more after the function has finished. But under the covers, again, there is more than just a "variable". There's an object, and a reference to that object. We generally think of the references as if they were the variables, because that makes sense and is usually the most convenient way to think of things. If I'm trying to explain the scope of variables created within a function to an inexperienced programmer, I'm going to hold off talking about passing by value vs passing by reference. But really, it's the objects that matter. And it's clear that queries and structures are passed by reference. You can see this clearly by assigning a query to a new name, and then changing the contents using either the original or the new name - you'll see the contents have changed for "both" (and of course, there's really only one query object in memory). To see this at work in the context of a function, write a function that creates a local query, copies that to a persistent variable (session, application, server) and returns the local query. Then, outside the function, change either the persistent query or the returned query, and you'll see that one changes the other, because again they actually point to the same object on the heap. Dave Watts, CTO, Fig Leaf Software http://www.figleaf.com/ http://training.figleaf.com/ Fig Leaf Software is a Veteran-Owned Small Business (VOSB) on GSA Schedule, and provides the highest caliber vendor-authorized instruction at our training centers, online, or onsite.

Top  |   Parent  |   Reply  |   Original Post  |   RSS Feed  |   Subscribe to this Group
Author:
Dave Watts
03/09/2010 10:38 PM

> You can circumvent this using duplicate( ) > > <cfset test = duplicate(test())/> > > Which makes a deep copy of the object by value. While you can do this, usually you shouldn't. Creating duplicate objects is expensive, which is why the default behavior of CF is to pass queries and structures by reference. This approach is common in many other programming languages as well. You should only create a deep copy when you explicitly want to have two separate variables that will presumably be manipulated in different ways. Dave Watts, CTO, Fig Leaf Software http://www.figleaf.com/ http://training.figleaf.com/ Fig Leaf Software is a Veteran-Owned Small Business (VOSB) on GSA Schedule, and provides the highest caliber vendor-authorized instruction at our training centers, online, or onsite.

Top  |   Parent  |   Reply  |   Original Post  |   RSS Feed  |   Subscribe to this Group
Author:
Mark A. Kruger
03/09/2010 10:45 PM

Very true Mark A. Kruger, MCSE, CFG (402) 408-3733 ext 105 www.cfwebtools.com www.coldfusionmuse.com www.necfug.com > You can circumvent this using duplicate( ) > > <cfset test = duplicate(test())/> > > Which makes a deep copy of the object by value. While you can do this, usually you shouldn't. Creating duplicate objects is expensive, which is why the default behavior of CF is to pass queries and structures by reference. This approach is common in many other programming languages as well. You should only create a deep copy when you explicitly want to have two separate variables that will presumably be manipulated in different ways. Dave Watts, CTO, Fig Leaf Software http://www.figleaf.com/ http://training.figleaf.com/ Fig Leaf Software is a Veteran-Owned Small Business (VOSB) on GSA Schedule, and provides the highest caliber vendor-authorized instruction at our training centers, online, or onsite.


<< Previous Thread Today's Threads Next Thread >>

Search cf-talk

May 24, 2012

<<   <   Today   >   >>
Su Mo Tu We Th Fr Sa
     1 2 3 4 5
6 7 8 9 10 11 12
13 14 15 16 17 18 19
20 21 22 23 24 25 26
27 28 29 30 31     

Designer, Developer and mobile workflow conference