Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do I have a lock here?

Tags:

See the following concurrent performance analysis representing the work done by a parallel foreach:

enter image description here

Inside the loop each thread reads data from the DB and process it. There are no locks between threads as each one process different data.

Looks like there are periodic locks in all the thread of the foreach due to unknown reasons (see the black vertical rectangles). If you see the selected locked segment (the dark red one) you will see that the stack shows the thread locked at StockModel.Quotation constructor. The code there just constructs two empty lists!

I've read somewhere that this could be caused by the GC so I've changed the garbage collection to run in server mode with:

<runtime>
    <gcServer enabled="true"/>
</runtime>

I got a small improvement (about 10% - 15% faster) but I still have the vertical locks everywhere.

I've also added to all the DB queries the WITH(NOLOCK) as I'm only reading data without any difference.

Any hint on what's happening here?

The computer where the analysis has been done has 8 cores.

EDIT: After enabling Microsoft Symbol servers turns out that all threads are blocked on calls like wait_gor_gc_done or WaitUntilGCComplete. I thought that enabling GCServer I had one GC for each thread so I would avoid the "vertical" lock but seems that it's not the case. Am I wrong?

Second question: as the machine is not under memory pressure (5 of 8 gigs are used) is there a way to delay the GC execution or to pause it until the parallel foreach ends (or to configure it to fire less often)?

like image 528
Ignacio Soler Garcia Avatar asked Feb 19 '13 16:02

Ignacio Soler Garcia


People also ask

What does a lock symbol mean?

The padlock symbol means the web page you are visiting is secure.

Why is there a lock on Snapchat?

The lock symbol next to a Snapchat story means that a particular story is private. This feature has been on the app for a long time and enables users to share any story only with a few people.

How do I remove the lock on my phone?

How to remove Screen Lock on your Android phone. Tap Settings > Security > Screen Lock. If prompted, enter your current lock screen code > None > Delete.

What is a lock screen on Android?

You can set up a screen lock to help secure your Android phone or tablet. Each time you turn on your device or wake up the screen, you'll be asked to unlock your device, usually with a PIN, pattern, or password. On some devices, you can unlock with your fingerprint.


1 Answers

If your StockModel.Quotation class allows for it, you could create a pool to limit the number of new objects created. This is a technique they sometimes use in games to prevent the garbage collector stalling in the middle of renders.

Here's a basic pool implementation:

    class StockQuotationPool
    {

        private List<StockQuotation> poolItems;
        private volatile int itemsInPool;

        public StockQuotationPool(int poolSize)
        {
            this.poolItems = new List<StockQuotation>(poolSize);
            this.itemsInPool = poolSize;

        }

        public StockQuotation Create(string name, decimal value)
        {
            if (this.itemsInPool == 0)
            {
                // Block until new item ready - maybe use semaphore.
                throw new NotImplementedException();
            }

            // Items are in the pool, but no items have been created.
            if (this.poolItems.Count == 0)
            {
                this.itemsInPool--;
                return new StockQuotation(name, value);
            }

            // else, return one in the pool
            this.itemsInPool--;

            var item = this.poolItems[0];
            this.poolItems.Remove(item);

            item.Name = name;
            item.Value = value;

            return item;
        }

        public void Release(StockQuotation quote)
        {
            if (!this.poolItems.Contains(quote)
            {
                this.poolItems.Add(quote);
                this.itemsInPool++;
            }
        }

    } 

That's assuming that the StockQuotation looks something like this:

  class StockQuotation
    {
        internal StockQuotation(string name, decimal value)
        {
            this.Name = name;
            this.Value = value;
        }


        public string Name { get; set; }
        public decimal Value { get; set; }
    }

Then instead of calling the new StockQuotation() constructor, you ask the pool for a new instance. The pool returns an existing instance (you can precreate them if you want) and sets all the properties so that it looks like a new instance. You may need to play around until you find a pool size that is large enough to accommodate the threads at the same time.

Here's how you'd call it from the thread.

    // Get the pool, maybe from a singleton.
    var pool = new StockQuotationPool(100);


    var quote = pool.Create("test", 1.00m);


    try
    {
        // Work with quote

    }
    finally
    {
        pool.Release(quote);
    }

Lastly, this class isn't thread safe at the moment. Let me know if you need any help with making it so.

like image 51
Mike the Tike Avatar answered Sep 28 '22 05:09

Mike the Tike