I need to know if there are some performance problem/consideration if I do something like this:
public Hastable Properties=...
public double ItemNumber
{
get { return (double)Properties["ItemNumber"]; }
set
{
ItemNumber = value;
Properties["ItemNumber"] = value;
}
}
Public string Property2....
Public ... Property 3....
Instead of accessing the property directly:
public string ItemNumber { get; set; }
public string prop2 { get; set; }
public string 3...{ get; set; }
It depends on your performance requirements... Accessing a Hashtable and casting the result is obviously slower than just accessing a field (auto-properties create a field implicitly), but depending on what you're trying to do, it might or might not make a significant difference. Complexity is O(1) in both cases, but accessing a hashtable obviously takes more cycles...
Well, compared to the direct property access it will surely be slower because much more code needs to be executed for the get and set operations. But since you are using a Hashtable the access should be pretty fast. You are also getting an additional overhead because of the casting since you are using weakly typed collection. Things like boxing and unboxing come with a cost. The question is whether all this will affect noticeably the performance of your application. It would really depend on your requirements. I would recommend you performing some load tests to see if this could be a bottleneck.
Related
Introduction to the goal:
I am currently trying to optimize performance and memory usage of my code. (mainly Ram bottleneck)
The program will have many instances of the following element at the same time. Especially when historic prices should be processed at the fastest possible rate.
The struct looks like this in it's simplest way:
public struct PriceElement
{
public DateTime SpotTime { get; set; }
public decimal BuyPrice { get; set; }
public decimal SellPrice { get; set; }
}
I realized the performance benefits of using the struct just like an empty bottle and refill it after consumption. This way, I do not have to reallocate memory for each single element in the line.
However, it also made my code a little more dangerous for human errors in the program code. Namely I wanted to make sure that I always update the whole struct at once rather than maybe ending up with just an updated sellprice and buyprice because I forgot to update an element.
The element is very neat like this but I have to offload methods into functions in another classes in order to have the functionality I require - This in turn would be less intuitive and thus less preferable in code.
So I added some basic methods which make my life a lot easier:
public struct PriceElement
{
public PriceElement(DateTime spotTime = default(DateTime), decimal buyPrice = 0, decimal sellPrice = 0)
{
// assign datetime min value if not happened already
spotTime = spotTime == default(DateTime) ? DateTime.MinValue : spotTime;
this.SpotTime = spotTime;
this.BuyPrice = buyPrice;
this.SellPrice = sellPrice;
}
// Data
public DateTime SpotTime { get; private set; }
public decimal BuyPrice { get; private set; }
public decimal SellPrice { get; private set; }
// Methods
public decimal SpotPrice { get { return ((this.BuyPrice + this.SellPrice) / (decimal)2); } }
// refills/overwrites this price element
public void UpdatePrice(DateTime spotTime, decimal buyPrice, decimal sellPrice)
{
this.SpotTime = spotTime;
this.BuyPrice = buyPrice;
this.SellPrice = sellPrice;
}
public string ToString()
{
System.Text.StringBuilder output = new System.Text.StringBuilder();
output.Append(this.SpotTime.ToString("dd/MM/yyyy HH:mm:ss"));
output.Append(',');
output.Append(this.BuyPrice);
output.Append(',');
output.Append(this.SellPrice);
return output.ToString();
}
}
Question:
Let's say I have PriceElement[1000000] - will those additional methods put additional strain on the system memory or are they "shared" between all structs of type PriceElement?
Will those additional methods increase the time to create a new PriceElement(DateTime, buy, sell) instance, respectively the load on the garbage collector?
Will there be any negative impacts, I have not mentioned here?
will those additional methods put additional strain on the system memory or are they "shared" between all structs of type PriceElement?
Code is shared between all instances. So no additional memory will be used.
Code is stored separately from any data, and the memory for the code is only dependent on the amount of code, not how many instance of objects there are. This is true for both classes and structs. The main exception is generics, this will create a copy of the code for each type combination that is used. It is a bit more complicated since the code is Jitted, cached etc, but that is irrelevant in most cases since you cannot control it anyway.
I would recommend making your struct immutable. I.e. change UpdatePrice so it returns a new struct instead of changing the existing one. See why is mutable structs evil for details. Making the struct immutable allow you to mark the struct as readonly and that can help avoid copies when passing the struct with an in parameter. In modern c# you can take references to structs in an array, and that also helps avoiding copies (as you seem to be aware of).
If I have an object A with many properties, out of which I only need a couple, I can boost performance by not transferring unnecessary data, i.e. selecting only the object properties I need into a new type B, either named or anonymous.
Now imagine I want to bind a list of those original objects A to, say, a datagridview, which only displays the couple of properties I want. I have created the datagridview columns using the property names of the original object A and set its datasource type to typeof(A). I was wondering, if I can select into the same object A just omitting the properties I don't need, i.e.
public class MyObject
{
public string prop1 { get; set; }
public string prop2 { get; set; }
.....
public string propN { get; set; }
}
var list = context.MyObject
.Select(n => new MyObject { prop1 = n.prop1, prop2 = n.prop2 }).ToList();
In this way I don't need to define a new type, either named or anonymous. The question is, do I gain something in performance, or I still have the overhead of the original large object A information, although I do not transfer data for all its properties.
Alex
Actually, I think, the performance can't improve much as Select statement will go through all your list and create a new list of objects for you. But if you have reference property that you don't use. You can save there.
If there is no complicated logic when you show data to UI. Whey don't you keep the model as it is.
If this is for UI display only - there is no performance gain. Whatever time you might gain you will lose by creating a new list of anonymous types.
However, if you intend to send this object through the network (as a response to a request for example), then this makes sense. This way fewer properties have to be serialized and sent through the network.
In most cases, however, you should worry with performance to this level. The user won't notice an improvement on such a level. If you really wish to improve the performance of your application, you should profile it and find the hotspots.
The only meaningful performance gain, assuming your constructor is "cheap", is in the SQL and data transport from/to.
That said, not everything is about performance. Sometimes it's about clarity, extensibility, decoupling, etc. Clarity wise, you're forcing others to have to ask the question "Is this property used by the UI?"
In addition to clarity issues, you have coupling between the UI and back-end entities. This is not ideal. A cheap/temporary solution might simply be one like this. Keeping in mind that it's still coupled due to the interface on the class, but it's something that would be trivial to adjust in the future if desired.
public interface IMyModel
{
string prop1 { get; set; }
string prop2 { get; set; }
}
public class MyObject : IMyModel
{
public string prop1 { get; set; }
public string prop2 { get; set; }
.....
public string propN { get; set; }
}
IEnumerable<IMyModel> list = context.MyObject
.Select(n => new { n.prop1, n.prop2 }) // only select these properties
.ToArray() // execute the query
.Select(n => (IMyModel)new MyObject { prop1 = n.prop1, prop2 = n.prop2 }); // construct our desired object
How to I check if a nested model object, has any items.
Ie. if I have an object/viewmodel:
public class CarViewModel
{
public string Type { get; set; }
public long ID { get; set; }
public virtual IQueryable<Feature> Features { get; set; }
}
public class Feature
{
public string Offer { get; set; }
public decimal Rate { get; set; }
public virtual CarViewModel CarViewModel { get; set; }
}
...and it is populated as follows - so that 1 car object has 2 additional features, and the other car object, has no additional features:
[
{"Type":"SoftTop","ID":1,
"Features":
[{"Offer":"Alloys","Rate":"500"},{"Offer":"Standard","Rate":"100"}]},
{"Type":"Estate","ID":2,
"Features":[]}
]
So in my code, I had "Cars" populated with the data above:
foreach (var car in Cars)
{
if (!car.Features.Any())
{
car.Type = "Remove";
}
}
However, I get the message: This method is not supported against a materialized query result. at the if (!car.Features.Any()) line.
I got the same error when trying if (car.Features.Count()==0)
Is there a way of checking if the number of Features is 0?
Or is there a linq way of removing any items from the object, where the number of features is 0?
Thank you,
Mark
UPDATE
I changed the viewModel to use IEnumerable and then the following:
cars=cars.Where(x => x.Feature.Count()>0).ToList();
That seems to work - although I'm not 100% sure. If anyone can say whether this is a "bad" fix or not, I'd appreciate it.
Thanks, Mark
Try fetching the results first then checking the count
car.Features.ToList().Count
I don't think there any anything wrong with the fix - when you're using IQueryable<T> that came from a Linq to DB (L2S, Entity Framework, etc) you pretty much have to materialise it before you can use things like Any() or Count() when you ask for these things inside foreach.
As to why this is - I actually am not 100% certain and I believe that the error is a bit misleading in this respect, but I think that what it's complaining about is that neither Cars not car.Features() has actually been fully evaluated and run yet (i.e you are only starting to hit the database at the point when you go foreach ... in your code because it's IQueryable<T>).
However on a broader note I'd recommend you not use IQueryable<T> in your Viewmodels, much safer to use IEnumerable<T> - no chance of accidentally setting off a database access when rendering your view, for example.
And also when you are returning data from your DataLayer or wherever, a good rule of thumb is to materialise it as quickly as possible so as to be able to move on with an actual list of actual things as opposed to a "promise to go and look" for certain things in the database at some unspecificed point in the future :) So your DataLayers should only ever return IEnumerable<T>'s
You can always cast an IEnumerable to IQueryable if for some reason you need to...
I have the follow example:
public class Commands
{
public int ID { get; set; }
public List<string> Alias { get; set; }
}
public class UserAccess
{
public int AccessID { get; set; }
// other stuff not needed for the question
public List<Commands> AllowedCommands { get; set; }
}
Now I wanted to implement on the UserAccess a way to return the command ID or NULL if no Alias were found on the list, see a dirty example of what I am saying below HasCommand:
public class UserAccess
{
public ID { get; set; }
// other stuff not needed for the question
public List<Commands> AllowedCommands { get; set; }
public Commands HasCommand(string cmd)
{
foreach (Commands item in this.AllowedCommands)
{
if (item.Alias.Find(x => string.Equals(x, cmd, StringComparison.OrdinalIgnoreCase)) != null)
return item;
}
return null;
}
}
My question is what would be the most efficient way to run or implement the HasCommand method ?
Or is there a better way to implement it into the UserAccess ?
Can be shortened a little bit
public Commands HasCommand(string cmd)
{
return AllowedCommands.FirstOrDefault(c => c.Alias.Contains(cmd, StringComparer.OrdinalIgnoreCase));
}
but it's pretty much the same thing.
public Commands HasCommand(string cmd)
{
return this.AllowedCommands.FirstOrDefault(item => item.Alias.Find(x => string.Equals(x, cmd, StringComparison.OrdinalIgnoreCase)) != null);
}
You do not need to use Where + FirstOrDefault. The FirstOfDefault can have condition.
Also, 3 suggestions for further improvement:
(1) I would encourage the use of IEnumerable instead of List, if possible.
(2) I would call "Commands" just "Command".
(3) I would make all commands be able to be easily referenced via a class like this:
public class Command {
public Command(int id, IEnumerable<string> aliases) {
Id = id;
Aliases = alias;
}
public int Id { get; set; }
public IEnumerable<string> Aliases { get; set; }
}
public class Commands {
public static readonly Command CommandNameHere1(yourIdHere1, yourAliasesHere1);
public static readonly Command CommandNameHere2(yourIdHere2, yourAliasesHere2);
//etc.
}
Assuming that by "efficient", you mean fast, anytime you are looking up a string in a collection of strings, and that collection is likely to contain more than a few entries, you should always use a hash lookup. Doing a simple scan of the list takes exponential time as the count of items goes up, while the count has little effect on a hash lookup. In .NET, this has traditionally been handled by the Dictionary class, which is commonly used to index a collection of objects with a key (which is often a string). However, the value can't be null, and this led to passing the same string in as both the key and value - rather ugly. Finally, .NET 4 provided HashSet, which you should use for such a case of only having a key and no value.
In your case, you have the (not uncommon) situation of needing a case-insensitive compare. The common solution for this is to lower-case the string keys when adding them to the dictionary (or HashSet). This tiny overhead on add is vastly outweighed by the savings on lookups, since all programmers should know and understand that case-insensitive compares are vastly slower than case-sensitive, especially with Unicode - the CPU can't just do a block compare of data, but must check each pair of characters specially (even using a table look-up, this is vastly slower).
If your Alias names can be in lower case, change them from List to HashSet. If not, use Dictionary where the key is added as lower case, and the value is the (mixed-case) Alias string. Assuming the use of Dictionary, your code would become:
public Commands HasCommand(string cmd)
{
foreach (Commands item in AllowedCommands)
{
if (item.Alias.ContainsKey(cmd))
return item;
}
return null;
}
Finally, also on the subject of performance, using LINQ is almost always going to result in slower performance - somewhere between a little slower and a lot slower, depending upon the situation. It does make nice, compact source for simple things, and I use it quite a bit myself, but if you're certain that performance is an issue for a piece of a code, you probably shouldn't use it (unless it's PLINQ, of course).
So, if you want as few lines of code as possible, use the other answer posted here. If you want speed, use mine.
It almost goes without saying, but when you're worried about the performance of some small chunk of code like this, just wrap it in a for loop and repeat it until it takes 5-10 seconds to execute - just add orders of magnitude as needed, whether it's 1,000 or 1,000,000 reps, and time it with System.Diagnostics.Stopwatch. Try alternative logic, and repeat the test. The 5-10 seconds is a minimum designed to mask the fluctuations caused by a managed environment and other stuff executing on the same machine (you should obviously also avoid running other apps during the test). Of course, for overall performance testing of a complicated application, a performance analyzer tool would be recommended.
If I use loops in the get of a property, does this mean every time I call get on the property, it executes the loop? For eg, below, if I call CartViewModel.Total, does this mean it executes the loop inside SubTotal and Discount?
public class CartViewModel
{
public decimal SubTotal { get { return CartViewItems.Sum(c => c.Price); } }
public decimal Discount { get { return CartViewItems.Sum(c => Total-SubTotal); } }
public decimal Total { get { return SubTotal-Discount; } }
public List<CartViewItem> CartViewItems { get; set; }
}
public class CartViewItem
{
public decimal Price { get; set; }
public int ProductId { get; set; }
public int Quantity { get; set; }
public float DiscountPercent {get; set;}
public decimal SubTotal { get { return Price*Quantity; } }
public decimal Total
{
get
{
return Convert.ToDecimal(((float)Price * (1 - (DiscountPercent / 100))
* Quantity));
}
}
}
Is there a way to optimize this?
Yes, every time you call the property, it will execute the loop.
Properties are really just syntactic sugar over method calls. Very nice syntactic sugar, but only sugar.
You might want to change CartViewModel to avoid exposing the list directly - instead, keep the list private, give some appropriate methods to mutate it (e.g. Add and Clear methods), probably make it implement IEnumerable<CartViewItem> itself, and keep track of the subtotal and discount as the list is mutated. That's assuming that CartViewItem is immutable, of course...
Alternatively (as John suggested), just make it more obvious that you're actually doing work, changing the properties to ComputeTotal(), ComputeDiscount() and ComputeSubTotal() methods.
I would recommend the "don't do that" approach.
Properties are meant for cases where the data being accessed are "almost like a field" in terms of performance and semantics. They are definitely not meant for cases where the property hides the fact that a more expensive operation is being performed.
Replace those properties with methods and see whether the calling code changes much. It will be clearer that you are doing something potentially expensive.
Depending on how often those are referenced, I might go further and inline the properties entirely. That might suggest some optimization in the callers.