当前位置: 首页 > 知识库问答 >
问题:

提高代码性能

巫马磊
2023-03-14

我有一个cron作业方法,它根据用户的特色故事构建用户的故事提要,跟踪类别并跟踪用户。

最终提要按正确顺序添加到以下数据库表中:
用户提要表:

Uid

方法如下,包含注释<代码:

public void ConstructUserFeed()
        {
            try
            {
                //get all user ids
                var userIds = userBL.GetIds();
                //get all featured stories
                var featStories = storyBL.GetFeaturedStories();

                if (userIds != null && userIds.Count > 0)
                {
                    foreach (var userId in userIds)
                    {
                        //integer List to store the stories ids in correct order
                        List<int> storyIdsLst = new List<int>();
                        //integer List for excluding duplicates
                        List<int> exceptStoryIds = new List<int>();
                        //user feed List to store the stories
                        var userFeed = new List<UserFeedDTO>();
                        //string to store the id list so we can add it later in db
                        string storyIds = "";

                        if (featStories != null && featStories.Count > 0)
                        {
                            foreach (var featStory in featStories)
                            {
                                //first add all the ids of featured stories except own user stories, ordered by date
                                if (featStory.authorId != userId)
                                {
                                    storyIdsLst.Add(featStory.id);
                                    exceptStoryIds.Add(featStory.id);
                                }
                            }
                        }

                        //get user's followed categories ids
                        var followedCategoryIds = userCategoriesBL.GetFollowedCategoryIds(userId);

                        if (followedCategoryIds != null && followedCategoryIds.Count > 0)
                        {
                            foreach (var categoryId in followedCategoryIds)
                            {
                                //get the user's 5 latest stories for every followed category
                                //except own stories and previous stories
                                var storiesByCateg = storyBL.GetByCategory(5, categoryId, userId, exceptStoryIds);

                                if (storiesByCateg != null && storiesByCateg.Count > 0)
                                {
                                    foreach (var storyByCateg in storiesByCateg)
                                    {
                                        userFeed.Add(storyByCateg);
                                        exceptStoryIds.Add(storyByCateg.id);
                                    }
                                }
                            }
                        }

                        //get user's followed users ids
                        var followedUserIds = userFollowersBL.GetFollowedUserIds(userId);

                        if (followedUserIds != null && followedUserIds.Count > 0)
                        {
                            foreach (var followedId in followedUserIds)
                            {
                                //get the user's 5 latest stories for every followed user
                                //except own stories and previous stories
                                var storiesByFollowedUsers = storyBL.GetByFollowedUser(5, followedId, userId, exceptStoryIds);

                                if (storiesByFollowedUsers != null && storiesByFollowedUsers.Count > 0)
                                {
                                    foreach (var storyByFollowedUsers in storiesByFollowedUsers)
                                    {
                                        userFeed.Add(storyByFollowedUsers);
                                    }
                                }
                            }
                        }

                        // order the stories by date
                        userFeed = userFeed.OrderByDescending(story => story.dateAdded).ToList(); 

                        if (userFeed != null && userFeed.Count > 0)
                        {
                            foreach (var story in userFeed)
                            {
                                //add the story ids after the featured story ids
                                storyIdsLst.Add(story.id);
                            }
                        }

                        //comma separated list of story ids as string so we can store it in db 
                        storyIds = string.Join(",", storyIdsLst.Select(n => n.ToString()).ToArray());

                        //create the UserFeed model
                        UserFeed userFeedModel = new UserFeed();
                        userFeedModel.userId = userId;
                        userFeedModel.storyListId = storyIds;
                        userFeedModel.lastUpdateTime = DateTime.Now;

                        userFeedBL.AddOrUpdateUserFeed(userFeedModel);
                    }
                    uof.Save();
                }
            }

            catch (Exception ex)
            {
                Console.WriteLine("Error occurred in processing job. Error : {0}", ex.Message);
            }
        }

对于30名用户,上述方法需要约35秒才能完成<问:我如何改进代码和性能?

共有1个答案

漆雕唯
2023-03-14

很难说是什么导致它执行如此缓慢,因此我建议使用SQL Server Profiler分析您的问题。检查您的查询是否被正确询问,并且没有做任何不必要的事情。

之后,我会考虑问更少的问题。因为你是在循环中做的,所以你可能会从做更少但更重的问题中受益。例如(假设userFollowersBL.*正在查询数据库):

var followedCategoryIds = userCategoriesBL.GetFollowedCategoryIds(userId);

我假设签名类似于:

IEnumerable<int> GetFollowedCategoryIds(userId);

考虑将其更改为:

IDictionary<int, IEnumerable<int>> GetFollowedCategoryIds(IEnumerable<int> userIds);

然后,在开始Foreach之前,您将在内存中拥有一个包含用户ID及其每个后续类别ID的字典。这样,您可以在一个查询中发送来自userBL. GetIds()的所有结果。这样做一次可能会提高性能,而不是30次。userFollowersBL. GetFolloweUserIds(userId)也是如此。

现在,您已经将对数据库的查询数量减少了约58倍。

public void ConstructUserFeed()
        {
            try
            {
                //get all user ids
                var userIds = userBL.GetIds();
                //get all featured stories
                var featStories = storyBL.GetFeaturedStories();

// Fetch all in one query.
IDictionary<int,IEnumerable<int>> allFollowedCategoryIds= userCategoriesBL.GetFollowedCategoryIds(userIds);
// Fetch all in one query
IDictionary<int,IEnumerable<int>> allUserFollowers = userFollowersBL.GetFollowedUserIds(userIds);

                if (userIds != null && userIds.Count > 0)
                {
                    foreach (var userId in userIds)
                    {
                        //integer List to store the stories ids in correct order
                        List<int> storyIdsLst = new List<int>();
                        //integer List for excluding duplicates
                        List<int> exceptStoryIds = new List<int>();
                        //user feed List to store the stories
                        var userFeed = new List<UserFeedDTO>();
                        //string to store the id list so we can add it later in db
                        string storyIds = "";

                        if (featStories != null && featStories.Count > 0)
                        {
                            foreach (var featStory in featStories)
                            {
                                //first add all the ids of featured stories except own user stories, ordered by date
                                if (featStory.authorId != userId)
                                {
                                    storyIdsLst.Add(featStory.id);
                                    exceptStoryIds.Add(featStory.id);
                                }
                            }
                        }

                        //get user's followed categories ids
                        var followedCategoryIds = allFollowedCategoryIds[userId]

                        if (followedCategoryIds != null && followedCategoryIds.Count > 0)
                        {
                            foreach (var categoryId in followedCategoryIds)
                            {
                                //get the user's 5 latest stories for every followed category
                                //except own stories and previous stories
                                var storiesByCateg = storyBL.GetByCategory(5, categoryId, userId, exceptStoryIds);

                                if (storiesByCateg != null && storiesByCateg.Count > 0)
                                {
                                    foreach (var storyByCateg in storiesByCateg)
                                    {
                                        userFeed.Add(storyByCateg);
                                        exceptStoryIds.Add(storyByCateg.id);
                                    }
                                }
                            }
                        }

                        //get user's followed users ids
                        var followedUserIds = allUserFollowers[userId];

                        if (followedUserIds != null && followedUserIds.Count > 0)
                        {
                            foreach (var followedId in followedUserIds)
                            {
                                //get the user's 5 latest stories for every followed user
                                //except own stories and previous stories
                                var storiesByFollowedUsers = storyBL.GetByFollowedUser(5, followedId, userId, exceptStoryIds);

                                if (storiesByFollowedUsers != null && storiesByFollowedUsers.Count > 0)
                                {
                                    foreach (var storyByFollowedUsers in storiesByFollowedUsers)
                                    {
                                        userFeed.Add(storyByFollowedUsers);
                                    }
                                }
                            }
                        }

                        // order the stories by date
                        userFeed = userFeed.OrderByDescending(story => story.dateAdded).ToList(); 

                        if (userFeed != null && userFeed.Count > 0)
                        {
                            foreach (var story in userFeed)
                            {
                                //add the story ids after the featured story ids
                                storyIdsLst.Add(story.id);
                            }
                        }

                        //comma separated list of story ids as string so we can store it in db 
                        storyIds = string.Join(",", storyIdsLst.Select(n => n.ToString()).ToArray());

                        //create the UserFeed model
                        UserFeed userFeedModel = new UserFeed();
                        userFeedModel.userId = userId;
                        userFeedModel.storyListId = storyIds;
                        userFeedModel.lastUpdateTime = DateTime.Now;

                        userFeedBL.AddOrUpdateUserFeed(userFeedModel);
                    }
                    uof.Save();
                }
            }

            catch (Exception ex)
            {
                Console.WriteLine("Error occurred in processing job. Error : {0}", ex.Message);
            }
        }

但老实说,这主要是猜测,可能会不时有所不同。根据我的经验,一次请求更多的数据,而不是多次请求相同的数据,往往会给您带来好处。

 类似资料:
  • 问题内容: 在代码底部运行的示例需要很长时间才能在我的机器上解决: 这是代码: 每只只供三只骆驼。我想至少这样做4次。该测试用例仍在运行(现在:()已经大约5分钟了。如果完成,我将对其进行更新。 我应该怎么做才能改善这段代码?(通常以性能为依据,但也欢迎其他建议)。 问题答案: 我以前也被这个绊倒了。这里的瓶颈实际上是。 该in语句是如此易于使用,你忘记了它是线性搜索,而当你在列表上进行线性搜索时

  • 将近200个nio线程处于相同的状态。可以做什么来使它的代码更可伸缩性,这样我们将获得更高的吞吐量。

  • 我反复调用以下代码,以从JSON响应中获取某些字符串值。 将其重构如下是否有意义,还是过度杀戮: 是否可以进一步重构,以便val1、val2、val3和val4作为参数传递给同一方法,并返回一个String?

  • 我正在用docx4j做一些测试。我需要做的是将复杂的Word文档(2-3页的文本、表格、项目符号列表、图像)转换成XHTML。

  • 我在我的应用程序中创建了第二个DataSource。 我用HikariDataSource创建了它,因为它断开了连接,所以出现了问题。 现在它没有断开,但是很慢 我的配置如下: 爪哇: 有人能告诉我如何提高绩效吗。 它们是表的小查询,分页约为25条记录,需要4秒钟。 我观察到,查询一个select的200条记录需要46秒,而查询只需要2秒。 以前,它们是千分之一秒。 非常感谢。

  • 在 Eclipse 中使用 5 个有用的插件来自动化代码质量分析 如果能在构建代码前发现代码中潜在的问题会怎么样呢?很有趣的是,Eclipse 插件中就有这样的工具,比如 JDepend 和 CheckStyle,它们能帮您在软件问题暴露前发现这些问题。在 让开发自动化 的本期文章中,自动化专家 Paul Duvall 将带来一些关于 Eclipse 插件的例子,您可以安装、配置和使用这些静态分析