ASP.NET Web API 2 Async les méthodes d'action de la Tâche.Run performance
Je suis en train de l'indice de référence (à l'aide d'Apache bench) un couple de ASP.NET l'API Web 2.0 des points de terminaison. L'un des qui est synchrone et un async.
[Route("user/{userId}/feeds")]
[HttpGet]
public IEnumerable<NewsFeedItem> GetNewsFeedItemsForUser(string userId)
{
return _newsFeedService.GetNewsFeedItemsForUser(userId);
}
[Route("user/{userId}/feeds/async")]
[HttpGet]
public async Task<IEnumerable<NewsFeedItem>> GetNewsFeedItemsForUserAsync(string userId)
{
return await Task.Run(() => _newsFeedService.GetNewsFeedItemsForUser(userId));
}
Après avoir regardé Steve Sanderson présentation, j'ai lancé la commande suivante ab -n 100 -c 10 http://localhost....
à chaque extrémité.
J'ai été surpris que les points de référence pour chaque point de terminaison semblait avoir à peu près la même.
Aller au large de ce que Steve a expliqué que je m'attendais à ce que l'async point de terminaison serait plus performant parce qu'il serait communiqué de pool de threads threads du pool de threads, immédiatement, les rendant ainsi disponibles pour d'autres demandes et d'améliorer le débit. Mais les chiffres semblent exactement la même.
Que suis-je malentendu ici?
OriginalL'auteur Simon Lomax | 2015-03-20
Vous devez vous connecter pour publier un commentaire.
À l'aide de
await Task.Run
pour créer "async" WebApi est une mauvaise idée - vous pourrez toujours utiliser un fil, et même de le même pool de threads utilisés pour les demandes.Cela conduira à des moments désagréables décrit dans le bon de détails ici:
Fondamentalement, vous ne laissez pas de l'asynchronie de l'ASP.NET - vous venez de cacher le CPU du code synchrone derrière la async façade.
Async
sur son propre est idéal pour les I/O bound code, car il permet d'utiliser le PROCESSEUR (threads) à leur haut rendement (pas de blocage pour les I/O), mais quand vous avez liée au Calcul de code, vous devrez toujours utiliser de l'UC à la même mesure.Et en tenant compte de la charge supplémentaire de
Task
et la commutation de contexte que vous obtiendrez même worser résultats que la simple synchronisation des méthodes de contrôleur.COMMENT LE RENDRE VRAIMENT ASYNC:
GetNewsFeedItemsForUser
méthode doit être transformé enasync
.:
async
variante (si il y a aucune mauvaise chance, vous aurez à la recherche de certains concurrents analogique)._newsFeedService.GetNewsFeedItemsForUser(userId)
est un appel à une base de données, qui je suppose est le réseau et e/S, pas de CPU. (2) Si c'est une bonne idée, comment devrait-code-elle être rédigée? Tous les exemples que je vois ne montrent que peu de code. Les exemples pourraient être utiles.Il suffit de chercher "C#, entity framework async" - msdn.microsoft.com/en-us/data/jj819165.aspx si vous utiliser entity framework ou "C# base de données asynchrone" -tugberkugurlu.com/archive/... si vous utilisez ADO standard.
Je suis en fait à l'aide de mongo et le c# pilote pour mongo, pas d'Entity Framework. Indépendamment de cela, de ce que vous dites, à moins que les appels que je suis en train de faire de ma méthode personnalisée
_newsFeedService.GetNewsFeedItemsForUser(userId);
sont asynchrones alors il n'y a pas de point d'essayer de faire de mon contrôleur de l'action méthode async.Il semble que MongoDB a quelques API asynchrone stackoverflow.com/questions/19740329/mongodb-net-async-await. Mais il faudra bien entendu changer le
GetNewsFeedItemsForUser
méthode de travail grâce à cette API. Il peut devenir un non trivial, mais très peu de changement difficile.OriginalL'auteur Eugene Podskal