Solved

C# Improve Threading Performance

Posted on 2011-09-12
8
363 Views
Last Modified: 2012-05-12
Hi

I have the following code as an example. I need to improve this code example that is very similar to the real code. Please if someone can help with some tips about improve this example. Thanks

class Program
    {
        static void Main(string[] args)
        {
            Game myGame = new Game();
            myGame.RunIt();
        }
    }


    class Game
    {
        List<Player> listPlayers = new List<Player>();
        Thread WrkThread = null;
        public void RunIt()
        {
            // set up the players
            listPlayers.Add(new Player("Tom", 100.0));
            listPlayers.Add(new Player("Jerry", 100.0));
            listPlayers.Add(new Player("Homer", 100.0));
            listPlayers.Add(new Player("Lisa", 200.0));

            // start a new thread that randomly redistribute their money
            WrkThread = new Thread(new ThreadStart(ThreadHandler));
            WrkThread.Start();

            // check periodically to remove losers
            while (true)
            {
                Thread.Sleep(1000);
                foreach (var x in listPlayers)
                {
                    if (x.money < 0.0)
                    {
                        Console.WriteLine("{0} has lost all money. Remove from table.", x.name);
                        listPlayers.Remove(x);
                    }
                }
            }
        }

        protected virtual void ThreadHandler()
        {
            Random rand = new Random();
            DateTime nextHandTime = DateTime.Now;
            while (true)
            {
                if (DateTime.Now < nextHandTime) continue;
                nextHandTime = DateTime.Now.AddSeconds(5);
                int winner = rand.Next(listPlayers.Count);
                double pot = 0;
                for (int i = 0; i < 4; i++)
                {
                    if (i != winner)
                    {
                        listPlayers[i].money -= 5.0;
                        pot += 5.0;
                    }
                }
                listPlayers[winner].money += pot;
            }
        }
    }


    class Player
    {
        public string name;
        public double money;
        public Player(string name1, double money1)
        {
            name = name1;
            money = money1;
        }
    }

Open in new window

0
Comment
Question by:JoseHidalgo
  • 4
  • 3
8 Comments
 
LVL 74

Expert Comment

by:käµfm³d 👽
ID: 36526913
I know this is going to sound silly, and I'm not trying to be rude, but have you done much threading?
0
 

Author Comment

by:JoseHidalgo
ID: 36526931
Actually is a small test. I submited this code but the lead is telling me that this code still have many problems that I need to tell him what are the problems.

Thanks
0
 

Author Comment

by:JoseHidalgo
ID: 36526944
For example

When the collection remove a player it will throw an error:

Collection was modified; enumeration operation may not execute.

0
 
LVL 74

Assisted Solution

by:käµfm³d 👽
käµfm³d   👽 earned 250 total points
ID: 36526965
The big thing with threading is the sharing of resources and/or objects. You have a shared object in listPlayers. Any time you have a shared object or resource, you can encounter instances of deadlocking (two threads each waiting for the other to release some resource) or race conditions (two threads trying to acquire some resource but who gets the resource is dependent on the results of the operations in the other thread). In your case, you have a race condition. Take a look at lines 36 and 50. Let's say the thread running line 50 is currently running. Line 50 executes. Then a context switch* occurs. Now you are running the thread that is on line 36. Line 36 is executed. Then another context switch occurs. Let's say you get to line 54. The value of winner is now 4 (because you initally loaded 4 objects into the list). However, line 36 has already executed on the other thread. How many items are actually in your list?


* A context switch is essentially when the CPU saves the current thread, loads a waiting thread, and begins executing it.
0
Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

 
LVL 74

Expert Comment

by:käµfm³d 👽
ID: 36526970
The value of winner is now 4
I didn't factor in the use of the rand.Next call, but the underlying concept I am discussing still holds.
0
 
LVL 74

Expert Comment

by:käµfm³d 👽
ID: 36526991
For example

When the collection remove a player it will throw an error:

Collection was modified; enumeration operation may not execute.
That error is not due to threading; rather it is because you are calling the Remove method inside of a foreach. You cannot remove items from a collection while inside of a foreach that is iterating over that same collection. To remove items in this manner use a for loop and do reverse iteration (i.e. length - 1 => 0).
0
 
LVL 40

Accepted Solution

by:
Jacques Bourgeois (James Burger) earned 250 total points
ID: 36527032
This might not make a big difference if you have only 4 players, but if the real application has more than that, calling AddRange once will all the players might improve the performance over adding them one by one.

-----

Then, a big question: why use a separate thread? This is a current misconception that threading will improve everything. 98% of the times i hear "Would multi-threading improve that routine?", the answer is No!

From what we have, your application does nothing but loop while the thread is running. Threading is usefull when many operations needs to run simultaneously. Starting a Thread and simply waiting for it to change something is overkill, you are making things more complex than could be.

Then, a loop that does almost nothing takes up CPU ticks anyway. That is one the best ways to lose performance, not enhance it.

We do not see the big picture, because "code example that is very similar to the real code" is not the same as the real code, and that can make a big difference. But from what I see there, a simple Timer would do the job more efficiently because you would not lose the CPU in the loop. Timers are usually the most effective way regularly check for a situation.

-----

For Collection was modified, this is normal. You cannot remove an element from a collection while you are looping through it with a foreach loop, because once the element is gone, so is the pointer to the next element. This is because of the way collections are stored and handled in memory. The problem can sometimes be solved by using a regular loop, the one with a counter, starting from the end going down (decrement the index instead of incrementing it). But it does not work will all collections, once again because of the way they are stored ans handled in memory.

Have a property in the Player class that defines if a player is active or not, and simply set that to False. The logic of the application would then be adapted to that property.
0
 

Author Closing Comment

by:JoseHidalgo
ID: 36527125
Thanks for the responses. Help me a lot
0

Featured Post

Enabling OSINT in Activity Based Intelligence

Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

Join & Write a Comment

Article by: Nadia
Suppose you use Uber application as a rider and you request a ride to go from one place to another. Your driver just arrived at the parking lot of your place. The only thing you know about the ride is the license plate number. How do you find your U…
Exception Handling is in the core of any application that is able to dignify its name. In this article, I'll guide you through the process of writing a DRY (Don't Repeat Yourself) Exception Handling mechanism, using Aspect Oriented Programming.
Excel styles will make formatting consistent and let you apply and change formatting faster. In this tutorial, you'll learn how to use Excel's built-in styles, how to modify styles, and how to create your own. You'll also learn how to use your custo…
Get a first impression of how PRTG looks and learn how it works.   This video is a short introduction to PRTG, as an initial overview or as a quick start for new PRTG users.

708 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

20 Experts available now in Live!

Get 1:1 Help Now