0

I am getting data from an external socket connection through the "Producer" below.

I place the data into a BlockingCollection, which is then read by the consumer. If the consumer does NOT receive data within a fixed period, it fires off anyway, such that my ProcessDataOnGrid, does something whenever data arrives OR AT LEAST after x millisecs.

The problem is that I have read that BlockingCollection is the preferred approach for this, BUT is appears very slow.

On average 150ms between when I get the external data and when I call ProcessDataOnGrid. Am I using this incorrectly, or is there a better way to wait for data BUT only for a fixed period of time?

public BlockingCollection<TickRecord> trPipe = new BlockingCollection<TickRecord>();

Producer:

public void ProcessMarketData(string key, string intraMessage)
{
    //////////
    //   Gets External data from intraMessage
    ////////////
    try
    {
        if (GRID!=null)
        {
            TickRecord tr = new TickRecord(intraMessage);

            while ( ! AddToFeedPipe(key, tr) )
            {
                Thread.Sleep(1000);
            }
        }
    }
    catch (Exception e)
    {
    }
  }
}

public bool AddToFeedPipe(string key, TickRecord tr)
{
        try
        {
            foreach (var s in cReader.STREAMS)
            {
                if (s.key == key)
                {
                    s.trPipe.Add(tr);
                    return true;
                }
            }

            return false;
        }
        catch (Exception)
        {
            return false;
        }
}

Consumer:

public void Read()
{
    DateTime DTNOW = DateTime.UtcNow;

    TimeSpan gridNextTS = G.gridNextDT.Subtract(DTNOW);

    try
    {
        if (trPipe.TryTake(out tr,gridNextTS) == false)
        {
            tr = trGAP;
        }
        else if (tr == null)
        {
            EOF = true;
            return;
        }

        ProcessDataOnGrid(tr);
    }
    catch (Exception e)
    {
        tr = null;
        EOF = true;
        return;
    }
}
marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
ManInMoon
  • 6,795
  • 15
  • 70
  • 133
  • `BlockingCollection` does not have an overload of `Add` which would return a boolean, so I can't wrap my head around your `while ( ! trPipe.Add( tr) )` line. – Kirill Shlenskiy Jul 12 '14 at 08:39
  • @KirillShlenskiy You are correct! I tried to simplify the example for this question. I have now edited to show code closer to my actual. – ManInMoon Jul 12 '14 at 09:01
  • your `BlockingCollection` is definitely not at fault here. Its performance footprint is quite small for what it does. Your `TryTake` logic also appears correct even if it is slightly unconventional. I am inclined to blame the `Thread.Sleep` which seems to be used for thread synchronisation purposes (correct me if I'm wrong here), but introduces a *huge* delay in doing so and is generally not the right tool for the job. It could also be something else though: hard to tell without seeing the rest of the code. – Kirill Shlenskiy Jul 12 '14 at 09:24
  • The sleep() only really gets called at the start when the pipe has not yet been fed. During normal running it doesn't get triggered. – ManInMoon Jul 12 '14 at 10:03
  • 1
    This is very hard to diagnose, especially if you're not showing the actual piece of code that reproduces the issue. I mean, it's good that you wanted to make it concise, but it would be better if you've managed to create a minimal *working* example that demonstrates your problem. – BartoszKP Jul 12 '14 at 10:35

1 Answers1

0

BlockingCollection is NOT slow. I had another thread competing for the same resource.

Many thanks.

ManInMoon
  • 6,795
  • 15
  • 70
  • 133