【问题标题】:Adding fixed size array to IEnumerable将固定大小的数组添加到 IEnumerable
【发布时间】:2013-09-07 15:33:58
【问题描述】:

这个方法得到:

IEnumerable<object[]> - 其中每个数组都是固定大小(它代表关系 数据结构)。

DataEnumerable.Column[] - 一些元数据列,大多数情况下,所有行的值都相同。

预期结果:

每个“行”都应该为这些列中的每一列获取值(因此数据结构保持相关性)。

    private IEnumerable<object[]> BindExtraColumns(IEnumerable<object[]> baseData, int dataSize, DataEnumerable.Column[] columnsToAdd)
    {
        int extraColumnsLength = columnsToAdd.Length;
        object[] row = new object[dataSize + extraColumnsLength];

        string columnName;
        int rowNumberColumnIndex = -1;

        for (int i = 0; i < extraColumnsLength; i++)
        {
            //Assign values that doesn't change between lines..
            // Assign rowNumberColumnIndex if row number column exists
        }

        //Assign values that change here, since we currently support only row number
        // i'ts not generic enough        
        if (rowNumberColumnIndex != -1)
        {
            int rowNumber = 1;

            foreach (var baseRow in baseData)
            {
                row[rowNumberColumnIndex] = rowNumber;

                Array.Copy(baseRow, 0, row, extraColumnsLength, dataSize);

                yield return row;

                rowNumber++;
            }
        }
        else
        {
            foreach (var baseRow in baseData)
            {
                Array.Copy(baseRow, 0, row, extraColumnsLength, dataSize);

                yield return row;
            }
        }
    }

这个方法可以从数百个具有相对大数据集的线程中调用,所以 这里的性能很关键,我尝试创建尽可能少的新对象。

请注意 - 这是一个私有方法,它使用 ONLY BY DataReader,它读取每一行,并立即将其传递给另一个数组在读取下一行之前 .

那么 - 在这里复制数组是否会以某种方式在这里进行优化,我应该(小心地)使用内存来提升这里的东西吗?

谢谢

【问题讨论】:

    标签: c# arrays enumerable


    【解决方案1】:

    您的代码从根本上被破坏了。您每次都只是返回对同一个数组的引用,这意味着除非调用者立即使用每个项目中的数据,否则它实际上会丢失。例如,假设我使用:

    List<object[]> rows = BindExtraColumns(data, size, toAdd).ToList();
    

    然后,当我遍历行时​​,我会在每一行中找到相同的数据。这真的不是一个很好的体验。

    我认为为每次迭代创建一个新数组会让更加更有意义。是的,这占用了很多额外的内存 - 但调用者并没有那么惊讶。

    如果您真的不想这样做,我建议您更改方法,以便调用者必须传入 Action&lt;object[]&gt; 才能在每一行上执行,并附带记录的附带条件,即如果调用者隐藏了引用到数组,他们可能会对结果感到惊讶。

    您显然非常关心性能,但如果您的数据来自数据库,我希望数组创建/复制性能微不足道。您应该首先编写最简单(也是最可靠)的代码,然后对其进行基准测试以查看其性能是否足够好。除非你有证据表明你需要做出这个令人惊讶的设计选择,否则感觉你优化得太早了。

    编辑:现在我们知道它是一个私有方法在一个特定的地方使用,我会仍然避免这种重用。它简直是脆弱的。我真的会改为传入Action&lt;object[]&gt;,或者每次都将数据复制到一个新数组中。如果没有强有力的证据证明这是一个瓶颈,我当然不会保留当前的方法:正如我之前所说,我希望数据库通信更加重要。像这样在代码中留下定时炸弹很少有效果。

    如果你真的,真的想要继续这样做,你应该非常强烈地记录它,并严重警告结果是非惯用的。

    就您是否可以进行 更多 优化而言 - 嗯...一种替代方法是首先避免使用单个数组。您可以创建一个包含对 both 数组(当前基行和固定数据)的引用的类,并公开一个索引器,该索引器根据请求的索引从一个数组或另一个数组返回值。我们不知道您对数据做了什么(“将其传递给另一个数组”实际上并没有任何意义)所以我们不知道这是否可行,但它会很有效并且 可以在没有奇怪行为的情况下实现。

    【讨论】:

    • 我有这个顾虑,我就按照你一开始说的那样写了。但是我怎么知道/处理内存限制?顺便说一句 - 它目前工作正常!
    • @Yosi:大概是因为您碰巧使用它的方式,它目前运行良好。这并不意味着它不会过于脆弱。至于“内存限制”——什么内存限制?您尚未准确解释该限制是什么,或者您是如何诊断的。
    • 首先,感谢您的帮助!我想我明白你的意思了。为每次调用创建如此多的数组对我来说似乎很可怕,但我想这可能不是问题,而且可以肯定的是,在你描述的内容之后,这段代码看起来很糟糕..
    • @Yosi:有什么理由不接受这个?它不工作吗?如果有,请提供更多详细信息。
    • @Yosi:查看我的编辑。仍然完全不清楚您实际上是否有任何证据表明这里的性能至关重要 - 您当然没有发布任何证据证明这一点(通过测量复制数组的影响来支持数据与读取数据的影响开始)。
    猜你喜欢
    • 2019-08-01
    • 1970-01-01
    • 1970-01-01
    • 2021-02-23
    • 2020-04-08
    • 2012-03-17
    • 1970-01-01
    • 2014-06-09
    • 1970-01-01
    相关资源
    最近更新 更多