[quote=334477:@Thomas Sanham]How does one tell if two string references refer to the same block of physical memory?
I need this ability for a system which computes memory usage of a running application using Introspection and Runtime.[/quote]
Using JUST introspection and Runtime you cant
You’d need to know if the internals pointed to the same memory location and that’s not accessible to you
I’m not sure what you mean Dave. I’m relating to you what engineers have explained to me going back years. Heck, I did a presentation at XDC a few years ago that included this bit of information and no engineer nor Geoff stood up and said, “no, that’s not true.” My presentation included the “proof” code I posted above which, if Xojo copied strings, should have crashed in short order. Try it yourself.
The behaviour you see at runtime IN XOJO CODE is NOT indicative of internal implementation
Strings are more like “copy on modify”
So
dim s1 as string = "foo"
dim s2 as string = s1 <<< s1 INTERNALLY has two "references" but you cant tell this from Xojo code alone
s2 = s2 + " bar" <<< s2 is newly "constructed" from s1 + new string literal and both s1 and s2 now have one INTERNAL reference
From the outside (ie/ Xojo code) you see the behaviour we want you to see
[quote=334482:@Kem Tekinay]Behind the scenes, strings do act like objects so code like this:
dim s1 as string = "hi there"
dim s2 as string = s1
will create two references to the same string. As such, if you code carefully, you can be reasonably sure that if StrComp( s1, s2, 0 ) = 0, it’s the same string reference.[/quote]
What you can tell is that they have the same contents
dim s1 as string = "foo"
dim s2 as string = "f"
s2 = s2 + "oo"
I believe ends up with two distinct internal references and no shared memory
Some weeks ago, I wrote a Method to rotate a picture (I found help here, thank you). I use this Method in two of my programs, but one of them was very faster than the other. I finally found why and I corrected the problem. I’m not sure to well remember, but as I remember, I did somewhere in my program (before I call the Rotate Method because I had something else to do on the picture) Picture1 = Picture2 instead of Picture1.Graphics.DrawPicture Picture2 . Even if Picture1 is Global and I did that in a Method where Picture2 was local. When I rotated Picture1 it was very long until I change the Picture1 = Picture2 -> Picture1.Graphics.DrawPicture Picture2 .
I remember Tim Hare explained some months ago (but I don’t find the post) which things were object and which where normal (what’s the name ?).
Example : FolderItem are objects ? Right ?
I like very much Xojo, but I program in my spare time and sometimes I stop use it for a long time, then I forget a little.
It would be very great for me if Xojo indicate with a color, with another symbol or I don’t know what when variable are objects and they become “linked” if we do Var1 = Var2 .
Example of what I mean : String1 = String2 or MyNumber1 = MyNumber2 is the “normal case” for guys like me. They are independents.
But if we write MyObject1 = MyObject2 ( FolderItem1 = FolderItem2 or Picture1 = Picture2 ) they become “linked”.
it would be very helpful* if the IDE would transform the = in <-> or == or another symbol to indicate.
*helpfull for me but maybe for a lot of persons.
And there do seem to be some “special cases”
For instance you’d think that, given whats been said, that
dim s1 as string = “foo”
dim s2() as string
for i as integer = 1 to 1000
s2.append s1
next
would append 1000 references
BUT put a larger number on there and you do see memory usage grow like this is appending copies NOT references
And append MAY in fact be a special cases where it does create new copies (I’d have to review array code to be sure)
And there could be other spots that have that kind of special behaviour
I’m not certain about what special cases exist in all of the classic framework
Strike that
This ISN"T special in any way
The array holds a pile of “references” to the internal string objects and they are handled just like every other string
FWIW I confirmed this with william and joe and what I posted (which is much like what Kem wrote) is how they are handled INTERNALLY
From outside the internal C++ runtime you cannot tell that this is the case and thats how it’s designed to be
dim s as string = M_String.Repeat( "12345", 1024 * 1024 )
redim Arr( -1 )
for i as integer = 1 to 1000000
dim x as string = s
Arr.Append x
next i
(Arr is a window property so it will not go away.)
Memory usage climbs to 64 MB while Virtual Memory is at 832 MB. Repeating a 5 MB string 1 million times should result in 5 TB of memory usage if the string were copied.
(Yes, I confirmed after the loop that the Arr.Ubound and s.Len were what I expected.)
Another way to look at this is to think about s = "some string" as shorthand for s = new string( "some string" ). If you can never affect the bytes of this imaginary string class, the whole concept makes a lot more sense. At least, it does to me.
You can find that in the LR. If Xojo considers something to be a datatype, it will be listed as such, and the same is valid for objects/classes.
In general, you can consider a (intrinsic) datatype as some memory structure where the memory reserved is equivalent to its value. At least in Xojo terminology; other languages may talk about intrinsic and extended datatypes instead, or whatever.
As a theoretical example: Assume
Dim i as int8 = 1
Here you can imagine 8 bits of memory (1 Byte) being reserved and the bit values being set to 00000001.
(The reality may be different technically, but lets ignore that.)
Dim i2 as int16 = 5
would result in RAM looking like 0000000000000101
and so on.
In most cases, datatypes will consume 4 or 8 bytes (32 or 64 bit), and their bits represent their value.
Object classes, like the folderitem, clearly need more than 4 or 8 bytes for all their values. So while again another 4 or 8 bytes are being reserved, they merely point to the real data of the object that resides somewhere else (Eli has recently posted a very good explanation about heap and stack handling if you are interested in the details.) A line like
Dim f1 as folderitem = anotherfolderitem
does simply copy the ptr to the real data of anotherfolderitem to f1, leaving the data itself untouched and unmoved.
And while this thread is a brilliant example that things are not always what they pretend to be a String being a datatype but under the hood it might be more complicated , you can assume that usually where the LR tells you that something is a datatype references to it will be handled by copying the data - by Value - while objects will copy the ptr to the data only (by Reference).
In general ANYTHING you create by using "New " is a Reference type
And doing V1 = V2 will “link” the two
They point to the same object or REFER to the same object
So changes to V1 appear to be reflected in V2 because of this.
Note that there are also lots of things that are REFERENCE types that you dont have to create by doing "NEW "
Controls. Windows. Menu Items etc are all reference types
In the old language reference the wiki page had a header that told you where an item inherited from and if that said “Object” then its a reference type (see http://documentation.xojo.com/index.php/Control)
As well Introspection/TypeInfo has two properties that tell you something very relevant
IsPrimitive As Boolean
Indicates the item is a primitive type, which are: Boolean, String, Color, Integer, Double, Single, Currency and other numeric types.
IsValueType As Boolean
Indicates the item is a value type, which means it is not a reference. With value types, assignments copy the value itself rather than the reference to the value. Primitive, pointer, structure and enum types are all value types.
Runtime.MemoryUsed is also useful to me to provide a summary of memory usage. But I am also attempting to produce a detailed description of memory usage including per-object and per-class.
Understood. I take it that it is impossible using pure Xojo?
Does there exist a 3rd party plugin function which achieves this?
[code]dim a as string = “Hello”
dim b as string = a // no copy
dim c as string = left(a,5) // no copy
dim d as string = “Hello” // gets same constant string
dim e as text = “Hello”
dim f as text = e // no copy
dim g as text = f.Left(5) // no copy
dim h as text = “Hello” // gets same constant text
dim pe as integer = GetTextMemoryAddressMBS(e)
dim pf as integer = GetTextMemoryAddressMBS(f)
dim pg as integer = GetTextMemoryAddressMBS(g)
dim ph as integer = GetTextMemoryAddressMBS(h)
dim i as auto = “Hello”
dim j as auto = i // no copy
dim k as auto = “Hello” // same text, but new auto object
dim l as auto = k // no copy
dim pi as integer = GetAutoMemoryAddressMBS(i)
dim pj as integer = GetAutoMemoryAddressMBS(j)
dim pk as integer = GetAutoMemoryAddressMBS(k)
dim pl as integer = GetAutoMemoryAddressMBS(l)
Break[/code]
The normal user doesn’t need to care and it just works fine. So when I run the code, I see that pa, pb, pc and pd are the same. Also pe, pf, pg are ph are the same. pi and pj are the same and pk and pl also.
The big surprise for me is that Left produces the same reference. That’s smart, but I don’t think it always did. (No need to correct me if I’m wrong, as I clearly don’t know the internals beyond what was explained to me.)