C#内存性能和加速

3

我有一个情况,每当用户按下键时,我需要处理一个包含2万个记录的不规则数组。我有一个网格,当用户输入内容时,系统会在网格中显示筛选后的结果。所以,我有一个填充有全部20k记录的不规则数组。然后,我有一个列表(控件全局可用),每次用户按下键时都会清空并填充只包含筛选后的记录,并将它们显示在网格中。

以下是代码:

the model
public struct PlayerLookUpAdapter
    {
        [Browsable(false)]
        public decimal Id { get; set; }
        [DisplayName("Número")]
        public String Number { get; set; }
        [DisplayName("Nombre")]
        public String Name { get; set; }
        [DisplayName("Apellido")]
        public String Surname { get; set; }
        [DisplayName("DNI")]
        public String Document { get; set; }
        [DisplayName("Estado")]
        public String Status { get; set; }
    }

private PlayerLookUpAdapter[] _source; // here are the 20k registers

List<PlayerLookUpAdapter> filteredOut = new List<PlayerLookUpAdapter>(); // here the filtered ones

// this code is executed every time the user press a key
private void tb_nro_KeyUp(object sender, KeyEventArgs e)
        {
            if (!(e.KeyCode.Equals(Keys.Enter) || e.KeyCode.Equals(Keys.Down)) && _source!=null)
            {
                String text = tb_nro.Text.ToUpper();
                if (String.IsNullOrEmpty(text))
                {
                    fg.DataSource = _source;
                    fg.Refresh();
                    return;
                }
                fg.DataSource = null;
                filteredOut.Clear();
                int length = _source.Length;
                for (int i = 0; i < length; i++)
                {
                    PlayerLookUpAdapter cur = _source[i];
                    if (cur.Number.ToUpper().StartsWith(text) || cur.Surname.ToUpper().StartsWith(text) || cur.Name.ToUpper().StartsWith(text))
                        filteredOut.Add(cur);
                }
                fg.DataSource = filteredOut;
                SetGridColumnsProperties();
                fg.Refresh();

            }
            else
            {
                fg.Focus();
            }
        }

从内存使用和性能方面来看,这是一个好的解决方案吗?您有什么建议?我该如何获得更高的速度。它运行得非常好,但如果我有10万个寄存器而不是2万个,会怎样呢?

提前感谢。


1
“但是如果我有10万个寄存器而不是2万个呢?”--你比我们更适合尝试这个。 - sehe
你有多大可能拥有10万个寄存器而不是2万个? - Phil Gan
没有用户喜欢深入挖掘一个包含 100,000 个选项的列表。在显示之前过滤结果集,一次只显示 10 个。 - Hans Passant
5个回答

3
我认为这是使用树的一个典型例子。
如果您将数据放在树中(我不知道C#/.Net是否支持树数据结构,或者您需要亲自动手)。
与在数组中搜索相比,在树中搜索的速度会增加(因为树具有类似于O(n)=n*log(n)的搜索速度)。
理论很简单:如果用户键入一个字面量,树就会转到以该字面量开头的节点,在这些节点上有所有可能的其他节点等等。例如:用户键入“t”,则转到“t”节点,然后键入“e”,则转到子节点“te”,有一些其他子节点,如“test”,系统将向用户提供这些子节点。

我会添加一些代码到后台线程来过滤数据,这样按键就可以立即返回并让用户继续输入。同时,只有在100毫秒后才开始过滤,以便让用户输入几个字符。 - CodingBarfield

1
首先,您可以稍微改进一下代码:StartWith方法有一个重载,它还接受字符串比较。您可以将其设置为“OrdinalIgnoreCase”,以避免将所有字符串转换为大写,但我认为您不会获得很多优势。 加速搜索的唯一方法是使用Lucene.net等搜索引擎。

http://www.codeproject.com/KB/library/IntroducingLucene.aspx


1

0
预先计算ToUpper()调用,这样您就不必每次都执行它。您可以维护第二个列表,其中存储了所有字符串的大写形式。
其次,如果搜索字符串中添加了一个键,则应在过滤列表(而不是整个列表)中进行搜索。新的(更长的)字符串永远不可能在过滤结果之外。

0

你可以在字符串比较时使用StringComparison.OrdinalIgnoreCase选项,避免调用20k次ToUpper

理想情况下,首先需要根据程序的典型使用情况进行最佳估计,确定什么速度过慢。毕竟过早优化是万恶之源


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接