Vector2 : Class or Struct? - c#

I want a simple Vector2 class/struct with float x and y and a couple methods.
I'm still trying to wrap my head around the differences but can't quite get it yet
I know it's usually done with structs, but i want to update a large 2D array of Vector2 every frame, would that make a class better than a struct ?
First post here by the way, and thanks for all replies in advance !

would that make a class better than a struct
for this operation, neither would be specifically any better or worse; however, having a lot of long-lived objects means you're likely to hit GC glitches. The fact that it is a "large 2D array" means that you can also potentially save a significant amount of overhead (object headers) by using structs.

Related

How do I optimize object creation as to avoid garbage collection?

I'm writing a Ray Tracer in C#. I use a Vector3 class for my points, normals, directions and colors. This class is instantiated numerous times per pixel. Is there a way I could structure my code as to avoid the massive amount of garbage collection I am seeing?
To anyone who finds this through the magic of Google. What I did was changing my Vector3 class to a Vector3 struct. This not only removed the massive GC overhead, but increased performance noticeable.
You can use Object Pool pattern to store and reuse your entities.
But i am not sure how big would be overhead in boxing/unboxing (if you use value types)

Game data - arrays of instances or arrays of values?

I'm making a game and need to store a fair bit of animation data. For each frame I have about 15 values to store. My initial idea was to have a list of "frame" objects that contain those values. Then I thought I could also just have separate lists for each of the values and skip the objects altogether. The data will be loaded once from an XML file when the game is started.
I'm just looking for advice here, is either approach at all better (speed, memory usage, ease of use, etc) than the other?
Sorry if this is a dumb question, still pretty new and couldn't find any info on stuff like this.
(PS: this is a 2D game with sprites, so 1 frame != 1 frame of screen time. I estimate somewhere around 500-1000 frames total)
If the animation data is not changing, you could use a struct instead of an class, which combines the "namespacing" of objects with the "value-typeness" of primitives. That will make all the values of a single frame reside in the same space, and save you some memory and page faults.
Just make sure that the size of your arrays doesn't get you into LOH if you intend to allocate and deallocate them often.
you are creating an animation So you should keep in mind a few basic things of.net:
Struct is created on stack. So, it is faster to instantiate (and destroy) a struct than a class.
On the other hand, every time you assign a structure or pass it to a function, it gets copied.
you can still pass struct by reference simply by specifying ref in the function parameter list
So it will be better to keep in mind this things

XNA VertexBuffer for Terrain Editor

I'm working on a personal project that, like many XNA projects, started with a terrain displacement map which is used to generate a collection of vertices which are rendered in a Device.DrawIndexedPrimitives() call.
I've updated to a custom VertexDeclaration, but I don't have access to that code right now, so I will post the slightly older, but paradigmatically identical (?) code.
I'm defining a VertexBuffer as:
VertexBuffer = new VertexBuffer(device, VertexPositionNormalTexture.VertexDeclaration, vertices.Length, BufferUsage.WriteOnly);
VertexBuffer.SetData(vertices);
where 'vertices' is defined as:
VertexPositionNormalTexture[] vertices
I've also got two index buffers that are swapped on each Update() iteration. In the Draw() call, I set the GraphicsDevice buffers:
Device.SetVertexBuffer(_buffers.VertexBuffer);
Device.Indices = _buffers.IndexBuffer;
Ignoring what I hope are irrelevant lines of code, I've got a method that checks within a bounding shape to determine whether a vertex is within a certain radius of the mouse cursor and raises or lowers those vertex positions depending upon which key is pressed. My problem is that the VertexBuffer.SetData() is only called once at initialization of the container class.
Modifying the VertexPositionNormalTexture[] array's vertex positions doesn't get reflected to the screen, though the values of the vertex positions are changed. I believe this to be tied to the VertexBuffer.SetData() call, but you can't simply call SetData() with the vertex array after modifying it.
After re-examining how the IndexBuffer is handled (2 buffers, swapped and passed into SetData() at Update() time), I'm thinking this should be the way to handle VertexBuffer manipulations, but does this work? Is there a more appropriate way? I saw another reference to a similar question on here, but the link to source was on MegaUpload, so...
I'll try my VertexBuffer.Swap() idea out, but I have also seen references to DynamicVertexBuffer and wonder what the gain there is? Performance supposedly suffers, but for a terrain editor, I don't see that as being too huge a trade-off if I can manipulate the vertex data dynamically.
I can post more code, but I think this is probably a lack of understanding of how the device buffers are set or data is streamed to them.
EDIT: The solution proposed below is correct. I will post my code shortly.
First: I am assuming you are not adding or subtracting vertices from the terrain. If you aren't, you won't need to alter the indexbuffer at all.
Second: you are correct in recognizing that simply editing your array of vertices will not change what is displayed on screen. A VertexBuffer is entirely separate from the vertices it is created from and does not keep a reference to the original array of them. It is a 'snapshot' of your vertices when you set the data.
I'm not sure about some of what seem to be assumptions you have made. You can, as far as I am aware, call VertexBuffer.SetData() at any time. If you are not changing the number of vertices in your terrain, only their positions, this is good. Simply re-set the data in the buffer every time you change the position of a vertex. [Note: if I am wrong and you can only set the data on a buffer once, then just replace the old instance of the buffer with a new one and set the data on that. I don't think you need to, though, unless you've changed the number of vertices]
Calling SetData is fairly expensive for a large buffer, though. You may consider 'chunking' your terrain into many smaller buffers to avoid the overhead required to set the data upon changing the terrain.
I do not know much about the DynamicVertexBuffer class, but I don't think it's optimal for this situation (even if it sounds like it is). I think it's more used for particle vertices. I could be wrong, though. Definitely research it.
Out of curiosity, why do you need two index buffers? If your vertices are the same, why would you use different indices per frame?
Edit: Your code for creating the VertexBuffer uses BufferUsage.WriteOnly. Good practice is to make the BufferUsage match that of the GraphicsDevice. If you haven't set the BufferUsage of the device, you probably just want to use BufferUsage.None. Try both and check performance differences if you like.

C# optimization - arrays / lists of value types and the stack (gaming)

I'm working on a game and am in the middle of a bit of AI number crunching and I want to optimize the code as much as I can. I have several structs in my code like Circle, Vector, etc. I want to reduce to a minimum the load on the GC as a result of this code since it will run many times a second and in each invocation will generate several large arrays and perform a lot of computations.
My question is, if I have a small method that can "return" multiple value types (i.e intersection of circle and vector, etc), what is the most performant way to transfer its result back to the main method?
I can think of a few ways to do it:
Return an array of the results i.e Vector[ ]
Return a List<Vector>
Pass in a List<Vector>
Any other way..?
What would be the best strategy to avoid a lot of small unnecessary objects / arrays on the heap that the GC then has to collect?
If you're in a situation where:
You're calling this method very frequently
You'll always be dealing with the same size of collection (or similar, at least)
You don't need the previous results by the time you next call it
... then you may be able to improve performance by repeatedly passing in the same array (or List<T>) and modifying it. On the other hand, you should absolutely measure performance before making any changes. You should also determine what's going to be "good enough" so you don't bend your code away from the most natural design any more than you have to.
This depends a lot of the type of your data passed, most times games use structs for vectors, intersection-data, etc...
When the data are structs you should avoid List<T> and passing per value because the data is copied then. But this depends a lot on the code, sometimes passing per value might be faster, sometimes not. I would make some performance tests. You can use this method for simple tests without a profiler:
public static Int64 MeasureTime(Action myAction)
{
var stopWatch = new Stopwatch();
stopWatch.Start();
myAction();
stopWatch.Stop();
return stopWatch.ElapsedMilliseconds;
}
When dealing with structs it might be always a good way to use out or ref.
More informations
All this situations may not cause a performance issue, they are just to explain best practices i learned when working with structs. To determine if ref and out are useful in each case you should make a performance test.
ref is used to avoid such situations:
Vector input = new Vector(x, y, z);
input = ModifyVector(input); // This line causes copies of the input vector and it's slow
The performance hit here depends a lot of the size of the Vector class, it's not a good practice to use the following method everytime. When returning a simple Int32 it's not necessary and should not be used to keep the code readable.
Right way:
Vector input = new Vector(x, y, z);
ModifyVector(ref input);
Of course the ref keyword could be used to make methods faster which return nothing, but this methods must take care about the data passed to them and should avoid modifing them. The speed benefit could be more than 50% in some situations ( I have a high-performance vector library and i tested many cases ).
out is used to avoid such situations:
Ray ray = ...;
CollisionData data = CastRay(ref ray); // Note the ref here to pass the Ray which contains 6 floats
CollisionData contains at least the point where it hits the ground and a normal. When using out here to get the result it should be much faster.
Right way:
Ray ray = ...;
CollisionData data;
CastRay(ref ray, out data);
When using arrays..
..you should know that a array is already a reference and you don't need the ref or out keyword to handle them. But when working with structs you should know that you are not holding references of the structs in your array. So when modifing a value of a array you can use ref myArray[0] to pass the value to a method and modify the struct at index zero in place without copying it. Also avoid to create new instances of them.
Don't know what is your platform/framework (XNA?), but I have encountered a problem with GC under Windows Phone 7 (7.5 got generational GC, but haven't test it). To avoid so called freezes of GC I made a collection where I pre-load all necessary data into Dictionary.
but first measure measure measure.

Small objects: create frequently or reuse?

For example, in draw method I need an instance of Rectangle to be used. Like this:
Rectangle rect = new Rectangle(FrameSize * CurrentFrame, 0, FrameSize, FrameSize);
Or other way. Define temp rectangle data member, and then use it like this:
rect.X = FrameSize * CurrentFrame;
rect.Y = 0;
rect.Width = FrameSize;
rect.Height = FrameSize;
Which way is better? One thing confuses me is that many rectangles created frequently, but many code solutions use first approach, while second one should be careful about memory consumptions.
Unless you have proved by careful measurement that reuse improves your performance you should create a new object every time.
.NET handles object creation and GC very efficient, you should not worry about any performance hit here. The second solution needs more careful coding to make sure you don't reuse objects in use somewhere else and you don't have previous state lugging around. Further more you will have more objects aging into gen1 or gen2 in the GC.
I would personally use the first approach in most cases - ideally making the type immutable if it makes sense and if the type is under your control.
The garbage collector is very good at reclaiming short-lived objects - and creating new objects means you don't need to worry about whether something still has a reference to the old object (thus making changes to it a problem).
How long lived are the objects? If they're only created locally and then used by the drawing methods, then chances are they will get collected in generation zero which is fairly efficient.
The problem with re-using a temp rectangle is that if you try to let it hang around beyond the life of a method it will be problematic for modifications in general.
As a general rule, I'd go with #1, and ONLY consider #2 if you discover later after profiling that #1 became an issue.
The former is safer when it comes to possible bugs, in respect to Rectangle class being mutable can produce some weird and hard to spot effects.
I don't think the performance penalty is serious enough to risk venturing in the wild world of mutable structs.
Consider the fact that structs are allocated on stack, in case of drawing method I personally would choose the first approach, as
Object created and initialized
Used
Pushed to GC as we leave the function.
So this is small object which is fast created and fast removed from the memory.
I would do it on an instance basis. You're not gaining much by reusing it, and it makes your code easier to break. By doing it on an instance basis, you can encapsulate some logic in a method and you won't have to worry about it breaking due to factors outside of the method.

Categories