-3

Sync Code:

public static void ImportData()
{

    for (var i = 0; i < 40000; i++)
    {
        DoSomething(i)
    }
}

Async Code:

public static void ImportDataAsync()
{
    for (int i = 0; i < 40000; i++)
    {
        await DoSomething(i)
    }
}

Just to be clear, that's one of my first attempt in async operation.

With the async code, my software it's really slow, when if i run synchronously multiple instance of the command line application it's 10x time faster.

I mean, i don't think that the DB access and the try/catch block of the GetAsync function will do this abissal difference between the two method, what do you think?

Edit: I don't know how to improve this question, but i will try to give an answer instead.

What i was asking is for the "Parallel.Foreach" method, what i was doing is thinking that the "await" prefix would set the current thread in standby creating another thread and continuing the for cycle, instead, what the await did is to simply leave that method until the awaited result, then he came back at the same point in the for cycle and resume it where he was awaiting.

I was just confusing things, specially in a Console Application actually i do not see any good reason to use await/async.

exSnake
  • 682
  • 1
  • 8
  • 26
  • 1
    Maybe take a look at https://stackoverflow.com/questions/18965200/difference-between-await-and-continuewith – Stefan Jul 09 '17 at 22:12
  • 2
    No way to answer without a good [mcve] that reliably reproduces the problem. But, some observations: the "fast" version appears to do 1/5th the work of the "slow" version. That would account for a 5x difference right there. Also, the "slow" version appears to allow up to 100 concurrent operations, which could create a lot of contention (unless you have 100 CPUs on both ends and a really fast network). Beyond that, you're using a "spin wait" to implement that throttling, which means you're tying up one CPU core 100% while you wait, which only makes everything else slower. – Peter Duniho Jul 09 '17 at 22:24
  • 3
    Fact is, if you've only got two CPU cores on your machine, and the "slow" version really is doing 5x the work, and most of the cost of the operation is local computation, the above observations would explain the 10x different entirely. If not, well...you still will need to fix the question so it includes a good [mcve], for anyone to diagnose you problem. Suffice to say, async done correctly won't impact performance in this type of scenario in any noticeable way, certainly nothing like a 10x difference. – Peter Duniho Jul 09 '17 at 22:25
  • 1
    How are we supposed to know WHY you did this wrong? Perhaps its just because you just are not very good? Maybe you meant to ask HOW is this wrong? – JK. Jul 09 '17 at 22:34
  • i was asking just because i was thinking about a wrong use of the "ContinueWith" method or a wrong use of the await method, if it's not that case so there is something very different between using the await/continuewith operation and run another instance of the same console application. I searched a lot before asking this question, it's like 2 weeks that i'm working on it, trying to implement async operation doing the best i can with my knowledge, but i'm failing hardly. – exSnake Jul 10 '17 at 00:41
  • 1
    I'm still learning and I'm still a bit confused about the async world however I believe that the main goal of using async code is not to make things faster but to not block the UI thread when doing sync stuff. You can run thousands of Get request simultaneously, at the end of the day, you are going to hit some limitations (network, server, thread pool to name only a few). And while you may think running everything in parallel should make things run faster, it may actually have opposite effect (think about all the work required to manage all the tasks etc...). – Etienne Jul 10 '17 at 02:20
  • https://stackoverflow.com/questions/36304986/whenall-on-the-large-number-of-task – Etienne Jul 10 '17 at 02:23
  • 1
    In a console app, async/await isn't so useful. I think a `Paralle.For()` would do better here, and it's much clearer. – H H Jul 10 '17 at 08:59
  • [Microbenchmarking](http://www.yoda.arachsys.com/csharp/benchmark.html) works best when there's no file I/O. – Stephen Cleary Jul 10 '17 at 14:52
  • I tried to clarify what i was asking for, after past a month of reasearch and studying, i don't know why people love to downvote who is trying to learn something and make a lot of effort trying to explain their problem. Fortunately there still is someone who pointed me to the right direction, even if my question was not comprehensible at all. Thanks to Hel Holterman,Francesco B and Peter Duniho who helped me. You know it's really hard to learn C# mechanism and is more than hard if you have to do everything by yourself. @Jk if i was "very good" I would not ask the question... Thx to Etienne too – exSnake Aug 30 '17 at 12:43

1 Answers1

1

At a first read, maybe could be this? 20 000 vs 100 000 iterations?

// Sync version
var start = 4000000;
var end = start + 20000;

// Async version
var start = 4000000;
var end = start + 100000

Also in your async method I see some things:

  1. public static void ImportAsyncData() should be public static async Task ImportAsyncData() to let the caller await your operation

  2. var slot = gs.GetAsync(c); I think here you want to await for that call: var slot = await gs.GetAsync(c); In this way you don't have to use ContinueWith, because your GetAsync call is awaited, so the next lines of code are executed only when or GetAsync task completes.

  3. You shouldn't wait with a "busy waiting" like this: while (requestDid - requestDone > 100);, you are using your CPU to just wait. In this case you could use a shared variable between your tasks with respect for the concurrence, maybe using some simple lock logic.

You can refactor it to something like this, but I didn't understand so much what you want to achieve and what is your problem :-)

public async Task ImportAsyncData()
{
    var gs = new Site();

    int requestDid = 0;
    int requestDone = 0;
    var found = 0;

    var watch = System.Diagnostics.Stopwatch.StartNew();
    var start = 4000000;
    var end = start + 100000

    var cod = "user"

    for (int i = start; i < end; i++)
    {
        var ts = watch.Elapsed;
        string elapsedTime = String.Format("{0:00}:{1:00}:{2:00}.{3:00}",
            ts.Hours, ts.Minutes, ts.Seconds, ts.Milliseconds / 10);

        Console.Title = "R: " + (i - start) + " F: " + found + " EL: " + ts;

        var c = cod + i;

        var user = await gs.GetAsync(c);
        if (user == null)
        {
            requestDone++;
            return;
        }

        using (var db = new Database())
        {
            found++;
            db.InsertUser(user);
        }

        requestDid++;
    }
}
Francesco Bonizzi
  • 5,142
  • 6
  • 49
  • 88
  • It's not the total time of execution where i see that it's really slow, i saw that in that in the for cycle, when with the Sync version he do like 5 request per seconds, in the async one he do 1/2 request per seconds then after some freeze waiting for request to complete, he starts again. About the Async Method, i don't want that the caller have to await my operation, it's not important. 2. If i await the request to be complete, won't the cycle stop until it is? 3. What you mean? Can i have some example? – exSnake Jul 10 '17 at 00:46
  • 1
    I think that first you should read a little of documentation to make some experience with Async/Await. That resources could be useful: [Doc 1](https://stackoverflow.com/questions/14455293/how-and-when-to-use-async-and-await), [Doc 2](https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/await), [Doc 3](https://stackoverflow.com/documentation/c%23/48/async-await#t=201707100750179333164) – Francesco Bonizzi Jul 10 '17 at 07:48