Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# huge performance drop assigning float value

Tags:

performance

c#

I am trying to optimize my code and was running VS performance monitor on it.

enter image description here

It shows that simple assignment of float takes up a major chunk of computing power?? I don't understand how is that possible.

Here is the code for TagData:

public class TagData
{
    public int tf;
    public float tf_idf;
}

So all I am really doing is:

float tag_tfidf = td.tf_idf;

I am confused.

like image 312
Chebz Avatar asked Dec 05 '13 20:12

Chebz


2 Answers

I'll post another theory: it might be the cache miss of the first access to members of td. A memory load takes 100-200 cycles which in this case seems to amount to about 1/3 of the total duration of the method.

Points to test this theory:

  1. Is your data set big? It bet it is.
  2. Are you accessing the TagData's in random memory order? I bet they are not sequential in memory. This causes the memory prefetcher of the CPU to be dysfunctional.
  3. Add a new line int dummy = td.tf; before the expensive line. This new line will now be the most expensive line because it will trigger the cache miss. Find some way to do a dummy load operation that the JIT does not optimize out. Maybe add all td.tf values to a local and pass that value to GC.KeepAlive at the end of the method. That should keep the memory load in the JIT-emitted x86.

I might be wrong but contrary to the other theories so far mine is testable.

Try making TagData a struct. That will make all items of term.tags sequential in memory and give you a nice performance boost.

like image 133
usr Avatar answered Nov 16 '22 01:11

usr


Are you using LINQ? If so, LINQ uses lazy enumeration so the first time you access the value you pulled out, it's going to be painful.

If you are using LINQ, call ToList() after your query to only pay the price once.

It also looks like your data structure is sub optimal but since I don't have access to your source (and probably couldn't help even if I did :) ), I can't tell you what would be better.

EDIT: As commenters have pointed out, LINQ may not be to blame; however my question is based on the fact that both foreach statements are using IEnumerable. The TagData assignment is a pointer to the item in the collection of the IEnumerable (which may or may not have been enumerated yet). The first access of legitimate data is the line that pulls the property from the object. The first time this happens, it may be executing the entire LINQ statement and since profiling uses the average, it may be off. The same can be said for tagScores (which I'm guessing is database backed) whose first access is really slow and then speeds up. I wasn't pointing out the solution just a possible problem given my understanding of IEnumerable.

See http://odetocode.com/blogs/scott/archive/2008/10/01/lazy-linq-and-enumerable-objects.aspx

like image 43
Nate Noonen Avatar answered Nov 16 '22 01:11

Nate Noonen