2

The only reason I'm posting this is because I actually believe that my code perfomance is being affected by this code block where I use a foreach loop inside another one.

I was wondering if anyone would suggest anything different that could help the performance or perhaps point out some other flaws in the code.

    public override void DisplayScore()
    {
        byte MessageLocation = 0;
        foreach (var kvp in PlayerScores.OrderByDescending((s => s.Value)))
        {
            if (MessageLocation == 5)
                break;

            if (MessageLocation == PlayerScores.Count)
                break;

            foreach (var player in PlayerList.Values)
            {
                SendMessage(MessageLocation, "My text");
            }
            Score++;
        }
    }

As you can see, it's just displaying the top 5 scores (in different locations) from a dictionary in a descending order and sending them to a list of players from another dictionary.

8
  • what is the content of send message? is this an email? Commented Jun 21, 2016 at 4:30
  • 2
    what is MessageLocation and where you are updating its value? Commented Jun 21, 2016 at 4:30
  • 3
    Your code looks bad, but it definitely does not generate any performance problems. Such simple constructions like foreach, break etc. will not cause performance problems until you have millions of records. Try to profile it, or at least try to debug it. Most probably, the problem is somewhere in SendMessage. Commented Jun 21, 2016 at 4:30
  • Process it in parallel, with for example Parallel.ForEach (easiest method). This way it will be as fast as you will get it for 2 simple loops i guess. Commented Jun 21, 2016 at 4:50
  • 1
    We can't really tell what's wrong without knowing how long things are taking, how large your collections are, or what SendMessage does. Please post a minimal reproducible example which demonstrates the problem. Commented Jun 21, 2016 at 6:13

2 Answers 2

1

I don't think that the double loop is the problem. I suggest to check the LINQ query PlayerScores.OrderByDescending((s => s.Value)). Depending on the numbers of scores this might take its time to order, espesially if the values come from a dictionary. The internal structure of a dictinary makes it expensive to enumerate through keys and values.

You can test it with the following code (slightly improved) and Visual Studio 2015, where it can be seen, how long single execution steps take:

public override void DisplayScore()
{

    var scores = PlayerScores.OrderByDescending(s => s.Value).Take(5).ToArray();

    foreach (var kvp in scores)
    {
        foreach (var player in PlayerList.Values)
        {
            SendMessage(MessageLocation, "My text");
        }
    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

I don't believe it's actually expensive to iterate over all the entries in a dictionary - it's just that it's not as quick as looking up by keys. Also note that the assignment to scores in your code will be very quick due to the lazy nature of LINQ queries - it's not actually doing any of the sorting at that point. If you wanted to actually split the LINQ part from the rest, you'd need to materialize the query.
Yes your right with the lazyness of LINQ. I edited my answer.
0

Instead of nested for loops you may gain some performance by adding the scores to a list and then sending them to the players eg:

//List containing player and score

foreach (var kvp in PlayerScores.OrderByDescending((s => s.Value)))
{
         //Add scores to list       
}

foreach (var player in PlayerList.Values)
{
         //Send scores to players
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.