I have a service that needs to read in messages from Amazon SQS as quickly as possible. We are expecting heavy traffic, and I'd like to be able to read in upwards of 10K messages/second. Unfortunately I'm currently at around 10 messages/second. Clearly, I have work to do.
This is what I'm using (converted to a console app to make testing easier):
private static int _concurrentRequests;
private static int _maxConcurrentRequests;
public static void Main(string[] args) {
_concurrentRequests = 0;
_maxConcurrentRequests = 100;
var timer = new Timer();
timer.Elapsed += new ElapsedEventHandler(OnTimedEvent);
timer.Interval = 10;
timer.Enabled = true;
Console.ReadLine();
timer.Dispose();
}
public static void OnTimedEvent(object s, ElapsedEventArgs e) {
if (_concurrentRequests < _maxConcurrentRequests) {
_concurrentRequests++;
ProcessMessages();
}
}
public static async Task ProcessMessages() {
var manager = new MessageManager();
manager.ProcessMessages(); // this is an async method that reads in the messages from SQS
_concurrentRequests--;
}
I'm not getting anywhere near 100 concurrent requests, and it doesn't seem to be firing OnTimedEvent
every 10 milliseconds.
I'm not sure if Timer
is the right approach here. I don't have much experience with this kind of coding. I'm open to trying anything at this point.
Update
Thanks to calebboyd, I'm a little closer to achieving my goal. Here's some really bad code:
private static SemaphoreSlim _locker;
public static void Main(string[] args) {
_manager = new MessageManager();
RunBatchProcessingForeverAsync();
}
private static async Task RunBatchProcessingForeverAsync() {
_locker = new SemaphoreSlim(10, 10);
while (true) {
Thread thread = new Thread(new ParameterizedThreadStart(Process));
thread.Start();
}
}
private static async void Process(object args) {
_locker.WaitAsync();
try {
await _manager.ProcessMessages();
}
finally {
_locker.Release();
}
}
I'm able to come close to reading a respectable number of messages per second with this, but the problem is my ProcessMessages
call never finishes (or maybe it would after a very long time). I'm thinking I probably need to limit the number of threads I have running at any one time.
Any suggestions on how I can improve this code so that ProcessMessages
has a chance to finish?