Let's say you havew a user class. When the user is logged in there are properties representing basic user info, an associated address and, say, 5 profile pictures, the last a generic lsit like this: Private _photos As List(Of Photo). However, instead of carrying the weight of the profile pictures in a session vairable, to reduce resource usage, I only want to populate them if the user needs to acces them. So, for the most part, the generic list of photo's is empty. Will it carry weight anyway? I'm trying to decide if I should just not populate ituntil needed, or if I should create an alternative "light" user class which doesn't have this property.
Provided the "heavy" properties are using a referenced type that will be allocated on the heap, and the allocation is not made until they are needed, they will have very little overhead. In most languages, the overhead will be platform specific, and usually equal to the size of a memory address (ie: a single pointer length, typically 32bit or 64bit per property).
For example, it looks like you're using VB.NET. The List(Of T)'s overhead will be minimal until you start adding elements to it. Then, you take the hit for each element. The List will allocate some initial buffer of pointers, so you'll get a pointer for the list (32/64bit), and an array to hold pointers, but none filled in. In general, you're not talking about a large amount of memory.
If, however, the properties are a value type (this depends on language a bit), they may get allocated in your class directly. This can cause them to have a high overhead in all cases. This is unlikely to be the case, though, since having "heavy" objects as value/stack allocated types is a bad design to begin with.
Assuming you are storing the paths in a RDB, the roundtrip time for requesting properties on demand are likely to be larger than just requesting them every time. However, you need to look at your usage: Will it be 9 of 10 times they need the path or 1 / 10?
Try it out both ways in a miniproject and then profile it. This is one of those times where there is no "right" answer.
Related
In Vulkan, I understand that a descriptor pool is used to allocate descriptor sets of some layout for use in a shader, but in the VkDescriptorPoolCreateInfo passed to vkCreateDescriptorPool, there is a field pPoolSizes that takes a bunch of objects containing a descriptor type and a number.
The documentation seems somewhat vague, but is this saying that a given descriptor pool can only have a certain, predetermined amount of each type of descriptor allocated from it in descriptor sets? If so, how do I determine how many I will need beforehand? What happens if it runs out?
Your understanding of descriptor pools is correct.
If so, how do I determine how many I will need beforehand?
That's up to you and your application's needs.
If your application needs to be completely flexible and freeform, then you will need to create descriptor pools dynamically as needed. If your application has greater foreknowledge of what the scene will look like, then your application will need fewer of such gymnastics.
Many serious Vulkan applications try to avoid having the number of descriptor sets be based on the number of objects in the scene. Push constants and/or dynamic UBO/SSBO descriptors allow different per-object state to be used without changing the descriptor itself. Textures for lots of objects can be bundled together into array textures, or depending on the hardware, arrays of textures.
In a perfect world, all meshes of a type (say, skinned meshes) could be rendered with the exact same descriptor set, using some per-object state to fetch the right matrix/texture data for that object.
But that's how they render. Such applications have firm control over the kinds of objects they render, what per-object data looks like, and so forth. Other applications may have different needs.
Vulkan is a tool; how you use it is entirely up to you.
What happens if it runs out?
Then you cannot allocate more descriptors from that pool. If you need to allocate another descriptor set, you will need to create another pool.
My approach was to have a class that initially allocates N of the descriptor, and if it runs out, it'll create another pool with N*2 entries. It'll keep doubling in size. It uses a simple linked lists and when it comes to allocating, it just tries the first one, and then moves onto the next if it's full.
That's all pretty inefficient, so I also had my code fire an assert if it ever had to create a second pool, that way I can make sure I choose a value of N that's big enough so that the retail version should never have to do it (but if it does somehow manage to due to some unforeseen set of circumstances, it'll still render correctly).
At the time, I remember cursing the spec and wishing descriptor pools would auto grow like command pools do. Still I imagine there's a good reason that they are like they are.
TLDR summary: (a) Should I include (lengthy) method code in classes which may spawn multiple objects at runtime, (b) does doing so cause memory usage bloat, (c) if so should I "outsource" the code to a class that is loaded only once and have the class methods call that, or alternatively (d) does the code get loaded only once with the object definition anyway and I'm worrying about nothing?
........
I don't know whether there's a good answer to this but if there is I haven't found it yet by searching in the usual places.
In my VB.Net (2010 if it matters) WinForms project I have about a dozen or so class objects in an object model. Some of these are pretty simple and do little more than act as data storage repositories. The ones further up the object model, however, have an increasing number of methods. There can be a significant number of higher level objects in use though the exact number will be runtime dependent so I can't be more precise than that.
As I was writing the method code for one of the top level ones I noticed that it was starting to get quite lengthy.
Memory optimisation is something of a lost art given how much memory the average PC has these days but I don't want to make my application a resource hog. So my questions for anyone who knows .Net way better than I do (of which there will be many) are:
Is the code loaded into memory with each instance of the class that's created?
Alternatively is it loaded only once with the definition of the class, and all derived objects just refer to that definition? (I'm not really sure how that could be possible given that, for example, event handlers can be assigned dynamically, but no harm asking.)
If the answer to the first one is yes, would it be more efficient to write the code in a "utility" object which is loaded only once and called from the real class' methods?
Any thoughts appreciated.
Go with whichever is going to be the easier to maintain codebase (shorter methods, etc). That is the more important cost with anything that has increasing complexity.
Memory optimization is only a problem if its a problem. 12 classes is really nothing, when you have hundreds of instances of hundreds of classes, then it may become a problem.
The short answer, it doesn't matter. Your data is stored in memory but your code is loaded only once.
EDIT: I guess I need a longer answer.
If you have 10 instances of a class, the variables that are part of that instance all take up thier own memory space. So if you have 10 properties, variables, etc, that means you have 100(ish) items in your memory. As for your code, it was loaded just once with your assembly. If you create 10 instances of your class, your code is not in memory 10 times.
I have a routine which accepts an object and does some processing on it. The objects may or may-not be mutable.
void CommandProcessor(ICommand command) {
// do a lot of things
}
There is a probability that the same command instance loops back in the processor. Things turn nasty when that happens. I want to detect these return visitors and prevent them from being processed. question is how can I do that transparently i.e. without disturbing the object themselves.
here is what i tried
Added a property Boolean Visited {get, set} on the ICommand.
I dont like this because the logic of one module shows up in other. The ShutdownCommand is concerned with shutting down, not with the bookkeeping. Also an EatIceCreamCommand may always return False in a hope to get more. Some non-mutable objects have outright problems with a setter.
privately maintain a lookup table of all processed instances. when an object comes first check against the list.
I dont like this either. (1) performance. the lookup table grows large. we need to do liner search to match instances. (2) cant rely on hashcode. the object may forge a different hashcode from time to time. (3) keeping the objects in a list prevents them from being garbage collected.
I need a way to put some invisible marker on the instance (of ICommand) which only my code can see. currently i dont discriminate between the invocations. just pray the same instances dont come back. does anyone have a better idea to implement this functionality..?
Assuming you can't stop this from happening just logically (try to cut out the loop) I would go for a HashSet of commands that you've already seen.
Even if the objects are violating the contracts of HashCode and Equals (which I would view as a problem to start with) you can create your own IEqualityComparer<ICommand> which uses System.Runtime.CompilerServices.RuntimeHelpers.GetHashCode to call Object.GetHashCode non-virtually. The Equals method would just test for reference identity. So your pool would contain distinct instances without caring whether or how the commands override Equals and GetHashCode.
That just leaves the problem of accumulating garbage. Assuming you don't have the option of purging the pool periodically, you could use WeakReference<T> (or the non-generic WeakReference class for .NET 4) to avoid retaining objects. You would then find all "dead" weak references every so often to prevent even accumulating those. (Your comparer would actually be an IEqualityComparer<WeakReference<T>> in this case, comparing the targets of the weak references for identity.)
It's not particularly elegant, but I'd argue that's inherent in the design - you need processing a command to change state somewhere, and an immutable object can't change state by definition, so you need the state outside the command. A hash set seems a fairly reasonable approach for that, and hopefully I've made it clear how you can avoid all three of the problems you mentioned.
EDIT: One thing I hadn't considered is that using WeakReference<T> makes it hard to remove entries - when the original value is garbage collected, you're not going to be able to find its hash code any more. You may well need to just create a new HashSet with the still-alive entries. Or use your own LRU cache, as mentioned in comments.
Why should someone ever use the non-NSMutable equivalents of the data structures in Objective-C? When it's a situation when you need a const object that should not be modified? Does using non-NSMutable classes improve performance in any way? Any other situations?
The two main reasons off the top of my head:
An object returning a property can be certain nobody will alter it if it's immutable. The object can therefore return the original instead of making copies all the time. So it's a memory and performance benefit.
When writing your own immutable objects, it's very easy to be thread safe. That naturally flows into being able to write multi-threaded functional-style code which is reasonably efficient and error free.
You also tend to see arguments in favour of the inherent preservation of the original value being useful, especially in terms of semantics and design patterns.
Immutable classes don't tend to be much more efficient in and of themselves with one exception — if you take an immutable copy of a mutable array, for example, then it's clear exactly how much storage is needed and exactly that much can be allocated. Because memory allocation costs time, mutable collections tend to keep some spare storage around because they can't predict how they're going to grow.
const is not directly related to non-mutable objects; I'm more familiar with the latter, so that's what I'll talk about.
A non-mutable object is like a reservation. Imagine that you work at a busy restaurant that only works on a reservation basis—all guests must make a reservation. When someone calls and makes a reservation for eight people at six, you know that you'll be expecting eight people at 6. Of course, this keeps things predictable. You know to set out one table that can sit eight people (it wouldn't make sense to use more than one table, especially at a busy restaurant). You notify the kitchen and tell them to expect eight orders a few minutes after six (okay, maybe you won't, but you might as well). In this way, everything runs smoothly and there are no delays. When the party of eight arrives promptly at six (because everyone in this world is perfectly punctual), you lead them right over to their seats, they order, and enjoy their meal. No problems whatsoever.
A problem arises if the reservation never specifies the number of people or the time. Imagine someone calls and tells you to expect a group of people for dinner. In this case, you have no information. A group could be a couple on a date, a four-person family, or two dozen people for a corporate function. They might arrive late because they were at a movie, really early because they have a young child, or at different times because it was impossible to coordinate everyone. In this case, you would have to scramble to find seating for everyone and the kitchens might suddenly be swamped with a large number of orders. Or you could have blocked off to many seats and the kitchen might find itself with nothing to do. In either case, where you over-estimate or under-estimate, there are delays and lost potential. Anything could happen.
In this metaphor, the restaurant would be the runtime system, and the reservations are the objects. In the first scenario, you have a non-mutable object, like an NSArray. The system knows how much data it'll hold, how many elements there are, and by runtime, what type they are. The system knows that the size won't change, so it can optimize RAM to go around that array, without leaving any precautionary bits. Everything runs smoothly because everything is known.
By contrast, nothing is known with an NSMutableArray. The user might add more elements, so the system has to scramble to find more RAM, rather than using those same clock cycles to crunch some operation; the user might replace an element in the middle with a larger one, having to offset all the later elements—which involves copying all tho elements after. In certain cases, it could involve copying all the elements of the array or string or whatever to a new location, a (potentially) expensive operation. This can impart a significant performance overhead, especially when you use a lot of them. In Java for example, concatenating a string involves copying the entire existing string to a new memory location, and leaving the garbage collector to deal with the old string.
Another compelling reason is that you make it a bit harder to change the data. Users (of the class) have to explicitly make a mutable copy, which helps to ensure that they know what they're doing. This advantage is particularly notable with multiple threads—you don't want to pass a mutable object to something that's running on a background thread, because the foreground thread (or any other) could then be modifying the object, as it's being modified by the original thread, leading to very interesting results.
I use to use Structures quite a lot in the VB6 days, and try to avoid them now with .NET. Just wondering if using structures in 2010 instead of a Class is considered nasty?
Thanks for the help.
Choosing a Structure takes consideration instead of being inherently "nasty". There are reasons why a Structure can be nasty; however there are also reasons a Class can be nasty in its own way...
Basically when you decide between these two object oriented kinds of containers, you're deciding how memory will be used.
There are different semantics associated with Structure and Class in VB.NET and they represent different memory usage patterns.
By creating a Class you're creating a reference type.
good for large data
memory contains a reference to the object location on the heap (like the concept of pointing to an object) though happens transparently to the VB.NET programmer because you're in "managed mode".
By creating a Structure you're creating a value type.
good for small data
memory allocated contains the actual value
be judicious because these are apt to get pushed on the stack area of memory (i.e. for local vars, but not class fields) - too large and you could run into stack issues.
Also some good video resources on YouTube if you're an audio learner.
Many articles on the Internet like these MSDN articles to teach the basics and details:
Value Types and Reference Types
7.1 Types - Reference and Value
MSDN Type Fundamentals - subheading: Reference and Value Types
Example
Structures exist because in some scenarios they make more sense than classes. They are particular useful for representing small abstract data types such as 3D points, latitude-longitude, rational numbers, etc.
The basic motivation for using structs is to avoid GC pressure. Since structs live inline (on the stack or inside whatever container you put them in) rather than on the heap, they typically result in far fewer small allocations, which makes a huge difference if you need to hold an array of one million points or rationals.
A key issue to watch out for is that structs are value types, and thus are generally passed around by value (the obvious exception being ref and out parameters). This has important implications. For instance:
Point3D[] points = ...;
points[9].Move(0, 0, 5);
The above code works fine, and increases the z coordinate of the 10th point by 5. The following code, however:
List<Point3D> points = ...;
points[9].Move(0, 0, 5);
Will still compile and run, but you will find that the z coordinate of the 10th point remains unchanged. This is because the List's index operator returns a copy of the point, and it is the copy that you are calling Move on.
The solution is quite simple. Always make structs immutable by marking all fields readonly. If you still need to Move points around, define + on the Point3D type and use assignment:
points[9] = points[9] + new Point3D(0, 0, 5);
It's considered pretty bad to use anything without understanding the implications.
Structures are value types, not reference types - and as such, they behave slightly differently. When you pass a value type, modifications are on a copy, not on the original. When you assign a value type to an object reference (say, in a non-generic list), boxing occurs. Make sure you read up on the full effect of choosing one over the other.
Read this for some understanding benefits of structures vs classes and vice-versa.
A structure can be preferable when:
You have a small amount of data and simply want the equivalent of the UDT
(user-defined type) of previous versions of Visual Basic
You perform a large number of operations on each instance and would incur
performance degradation with heap management
You have no need to inherit the structure or to specialize
functionality among its instances
You do not box and unbox the structure
You are passing blittable data across a managed/unmanaged boundary
A class is preferable when:
You need to use inheritance and polymorphism
You need to initialize one or more members at creation time
You need to supply an unparameterized constructor
You need unlimited event handling support
To answer your question directly, there is nothing inherantly wrong with using a structure in VB.NET. As with any design decision you do need to consider the consequences of this decision.
It's important that you're aware of the difference between a class and a structure so that you can make an educated decision about which is appropriate. As stated by Alex et al, one of the key differences between a structure and a class is that a structure is considered a value type and a class is considered a reference type.
Reference types use copy-by-reference sematics, this means that when an object is created or copied, only a pointer to the actual object is allocated on the stack, the actual object data is allocated on the heap.
In contrast, value types have copy-by-value sematics which means that each time a value type (e.g. a structure) is copied, then the entire object is copied to a new location on the stack/
For objects with a small amount of data, this isn't really a problem, but if you have a large amount of data then using a reference type will likely be less expensive in terms of stack allocations because only a pointer will be copied to the stack.
Microsoft have guidelines on the use of structures that more precisely describe the differences between classes and structures and the consequences of choosing one over the other
From a behavioral standpoints, there are three types of 'things' in .net:
Mutable reference types
Value types which can be mutated without being entirely replaced
Immutable reference and value types
Eric Lippert really dislikes group #2 above, since .net isn't terribly good at handling them, and sometimes treats them as though they're in group #1 or #3. Nonetheless, there are times when mutable value types make more sense semantically than would anything else.
Suppose, for example, that one has a rectangle and one wants to make another rectangle which is like the first one, but twice as tall. It is IMHO cleaner to say:
Rect2 = Rect1 ' Makes a new Rectangle that's just like Rect1
Rect2.Height = Rect2.Height*2
than to say either
Rect2 = Rect1.Clone ' Would be necessary if Rect1 were a class
Rect2.Height = Rect2.Height*2
or
Rect2 = New Rectangle(Rect1.Left, Rect1.Top, Rect1.Width, Rect1.Height*2)
When using classes, if one wants an object that's slightly different from an existing object, one must consider before mutating the object whether anyone else might want to use the original; if so, one must make a copy of it and then make the desired changes to the copy. With structs, there's no such restriction.
A simple way to think of value types is to regard every assignment operation as making a clone of the original, but in a way that's considerably cheaper than cloning a class type. If one would end up cloning a lot of objects as often as one would assign references without cloning, that's a substantial argument in favor of structs.