VB / C#按键分组对象 - 性能(内存)问题

时间:2010-12-08 01:45:29

标签: c# .net vb.net performance logging

我正在阅读日志文件。

我的目标是显示网站上最受欢迎的10个网址。

执行此操作的一种方法是读取所有日志条目并将每个URL保存到Dictionary。字典将URL作为密钥,将访问次数作为值。如果字典中存在URL,则该URL的Key的值增加+1,否则添加值为1的新Key / Value对。

处理完成后,字典按值排序,并显示前10个条目。

这可能会有效,但是当处理具有数千个不同页面网址的网站的日志文件时(考虑查询字符串),它可能会导致严重的内存问题。

由于我只需要前10个条目,是否有办法避免将所有网址放入内存并仍然获得前10个网址+访问次数?

3 个答案:

答案 0 :(得分:5)

对于大多数理智的数据集,这不会导致严重的内存问题 除非您在Google工作,否则您不会遇到任何内存问题 过早的优化是邪恶的。

如果在实现它之后,只有内存问题,则应切换到SQL数据库。

编辑 :(回复您的评论)
10,000个不同的500个字符的字符串将使用10,000 * 500 * 4个字节= 20MB,这非常少。 (它还会更多地用于字符串管理和字典本身,但总共不到1MB) 在您开始获得数百万个唯一 500个字符的网址之前,您无需担心。

答案 1 :(得分:0)

创建前10个网址的准确图表,没有。 但是,你可以做的是抽样,或者摆脱那些没有机会进入前10名的网页,例如,缓存每一页的访问一天,只跟踪前100页,除此之外,你' d需要存储每个页面的访问次数。

答案 2 :(得分:0)

如果你可以将它全部放入一个字典中,那就去做吧。

...但是我们假设你的日志文件有太多的URL不适合单个字典。

  1. 将日志文件分成两半。
  2. 如上所述,将日志文件的前半部分放入Dictionary0,这样就可以Dict0(URL) = count
  3. 现在反转该字典并对其进行排序,以便您拥有RevDict0(Count) = {URL0,URL1,...}
  4. 在VB.Net中,这里是如何反转字典:

    Dim RevDict0 as Dictionary(of Integer, List(of String))
    For Each url as String in Dict0
        If Not RevDict0.Contains(Dict0(url)) Then
            RevDict0.Add(Dict0(url), new List(of String))
        End If
        RevDict0(Dict0(url)).Add(url)
    Next
    

    现在看一下RevDict0的第11个索引RevDict0.Keys.Sort.Reverse.item(11)。例如,假设该数字为90.现在关闭日志文件和字典以释放内存,然后使用日志文件的后半部分再次启动以生成Dict1和RevDict1。检查RevDict1.Keys.Sort.Reverse.Item(11)。让我们假设这个数字是40.现在我们知道上半场任何不到50次访问的URL都不能超过90次访问(50 + 40)所以它不会超过90次访问不可能进入最后十强。

    现在我们释放除了RevDict1的前十名以外的所有内容。

    现在:

    1. 使用日志文件的前半部分构建FinalDict(of String, Integer)(如果您之前存储了Dict0,则从磁盘读取)。
    2. FinalDict中删除不在RevDict1中的少于50次访问的内容,以释放内存。
    3. 使用日志文件的后半部分添加到FinalDict
    4. 注意:

      • 您最终会进行多次通过,但您的内存中没有URL。
      • 如果第11个指标(90和40)相距足够远,你可以释放很多FinalDict个成员,它只会节省内存。
      • 如果事实证明下半场的第11个索引大于第一个(40和90而不是90和40)那么你需要读取日志文件的后半部分,然后是第一个,并使用Dict1而不是Dict0等。
      • 这很笨拙;必须有更聪明的东西!