【发布时间】:2016-02-11 16:30:42
【问题描述】:
出于某种原因,这段特定的代码在生产服务器(即 XL Azure 云服务)上的运行速度比在本地主机上慢得多。最糟糕的是,这种慢度并不一致,即大部分时间它很慢,但有时它运行得很快。慢是指这段代码在生产环境中运行需要 4.000 毫秒(我知道这一点是因为我使用的是 Azure AppInsights),而在本地主机上只需要大约 60 毫秒。我无法弄清楚为什么会这样。这是代码(请注意,这只是较大方法的一部分,但我确信这部分是最慢的,其他一切都快得多):
for (var i = 0; i < feedDeserialized.Length; i++)
{
RedisWorkoutItem workout;
bool hasRespected;
string username, fullName, profilePic;
// usersFromRedis is an array of Dictonary <string,string>
var userRedis = usersFromRedis[i];
// workoutsFromRedis is just an array of objects - RedisValue object
var stringWorkout = workoutsFromRedis[i];
// just an array of objects - RedisValue object
var workoutComment = commentsFromRedis[i].HasValue ? commentsFromRedis[i].ToString() : "";
if (userRedis != null)
{
profilePic = userRedis["ProfilePhotoUrl"].HasValue
? userRedis["ProfilePhotoUrl"].ToString()
: "";
fullName = userRedis["FirstName"] + " " + userRedis["LastName"];
username = userRedis["UserName"].HasValue ? userRedis["UserName"].ToString() : "";
}
//code inside this else statement never happens
else
{
var stopWatch2 = new Stopwatch();
stopWatch2.Start();
var user = databaseContext.Users.Find(feedDeserialized[i].UserId);
profilePic = user.ProfilePhotoUrl;
username = user.UserName;
fullName = user.FirstName + " " + user.LastName;
stopWatch2.Stop();
telemetryHelper.TrackEvent(_telemetryClient,
"CreateRedisFeedViewModelAsync: Went to DB for user", stopWatch2.Elapsed);
}
if (stringWorkout.HasValue)
{
workout = JsonConvert.DeserializeObject<RedisWorkoutItem>(stringWorkout);
hasRespected = workout.UsersWhoRespected.Contains(userId);
}
//code inside this else statement never happens
else
{
var stopWatch2 = new Stopwatch();
stopWatch2.Start();
var workoutGuid = Guid.Parse(feedDeserialized[i].WorkoutId);
var workoutFromDb = await databaseContext.Trenings.FindAsync(workoutGuid);
var routine = await databaseContext.AllRoutineses.FindAsync(workoutFromDb.AllRoutinesId);
workout = new RedisWorkoutItem
{
Name = routine.Name,
Id = workoutFromDb.TreningId.ToString(),
Comment = workoutFromDb.UsersCommentOnWorkout,
DateWhenFinished = workoutFromDb.DateTimeWhenTreningCreated,
NumberOfRespects = workoutFromDb.NumberOfLikes,
NumberOfComments = workoutFromDb.NumberOfComments,
UserId = workoutFromDb.UserId,
Length = workoutFromDb.LengthInSeconds,
Points = workoutFromDb.Score
};
workoutComment = workoutFromDb.UsersCommentOnWorkout;
hasRespected = databaseContext.TreningRespects
.FirstOrDefault(r => r.TreningId == workoutGuid && r.UserId == userId) != null;
stopWatch2.Stop();
telemetryHelper.TrackEvent(_telemetryClient,
"CreateRedisFeedViewModelAsync: Went to DB for workout", stopWatch2.Elapsed);
}
string workoutLength;
if (workout.Length >= 3600)
{
var t = TimeSpan.FromSeconds(workout.Length);
workoutLength = $"{t.Hours:D2}:{t.Minutes:D2}:{t.Seconds:D2}";
}
else
{
var t = TimeSpan.FromSeconds(workout.Length);
workoutLength = $"{t.Minutes:D2}:{t.Seconds:D2}";
}
listToReturn.Add(new FeedMobileHelper
{
Id = feedDeserialized[i].Id.ToString(),
UserId = workout.UserId,
WorkoutId = feedDeserialized[i].WorkoutId,
Points = workout.Points.ToString("N0", new NumberFormatInfo
{
NumberGroupSizes = new[] {3},
NumberGroupSeparator = "."
}),
WorkoutName = workout.Name,
WorkoutLength = workoutLength,
NumberOfRespects = workout.NumberOfRespects,
NumberOfComments = workout.NumberOfComments,
WorkoutComment = workoutComment,
HasRespected = hasRespected,
UserImageUrl = profilePic,
UserName = username,
DisplayName = string.IsNullOrWhiteSpace(fullName) ? username : fullName,
TimeStamp = workout.DateWhenFinished,
DateFormatted = workout.DateWhenFinished.FormatDateToHrsDaysWeeksString()
});
}
我不明白为什么这需要 4 秒才能在具有 8 个内核和 15 GB RAM 的云服务上完成,尤其是因为这里没有什么花哨的东西,没有访问数据库(正如我在 cmets 中指出的那样代码永远不会执行)或磁盘,一切都在内存中完成。循环中的大多数事情都是在恒定时间内完成的 - O(1)。请任何人都可以帮我弄清楚这里有什么问题。
还有一件事,执行这部分代码的 API 调用不会被 1000 多个用户同时调用,它只被我调用(我很确定)。
附言
feedDeserialized.Length 约为 60
【问题讨论】:
标签: c# performance azure asp.net-web-api azure-cloud-services