自定义提取器上的 OutOfMemory

OutOfMemory on custom extractor

我已经将很多小的 XML 文件拼接成一个文件,然后制作了一个自定义提取器到 return 行,每个文件对应一个字节数组。

  1. 运行 在 remote/master
    • 运行 一个文件(gzipped,11Mb),它工作正常。
    • 运行它对于多个文件,我得到一个System.OutOfMemoryException。
  2. 运行 在 local/master
    • 运行 它适用于一个或多个文件(gzipped 500+ Mbs),工作正常。

提取器如下所示:

public override IEnumerable<IRow> Extract(IUnstructuredReader input, IUpdatableRow output)
    {

        using (var stream = new StreamReader(input.BaseStream))
        {
            var xml = stream.ReadToEnd();

            // Clean stiched XML
            xml = UtilsXml.CleanXml(xml);

            // Get nodes - one for each stiched file
            var d = new XmlDocument();
            d.LoadXml(xml);
            var root = d.FirstChild;

            for (int i = 0; i < root.ChildNodes.Count; i++)
            {
                output.Set<object>(1, Encoding.ASCII.GetBytes(root.ChildNodes[i].OuterXml.ToString()));
                yield return output.AsReadOnly();
            }

            yield break;
        }
    }

错误消息如下所示:

==== Caught exception System.OutOfMemoryException

at System.Xml.XmlDocument.CreateTextNode(String text)
at System.Xml.XmlLoader.LoadAttributeNode()
at System.Xml.XmlLoader.LoadNode(Boolean skipOverWhitespace)
at System.Xml.XmlLoader.LoadDocSequence(XmlDocument parentDoc)
at System.Xml.XmlDocument.Load(XmlReader reader)
at System.Xml.XmlDocument.LoadXml(String xml)
at Microsoft.Analytics.Tools.Formats.Text.XmlByteArrayRowExtractor.<Extract>d__0.MoveNext()
at ScopeEngine.SqlIpExtractor<ScopeEngine::GZipInput,Extract_0_Data0>.GetNextRow(SqlIpExtractor<ScopeEngine::GZipInput\,Extract_0_Data0>* , Extract_0_Data0* output) in d:\data\ccs\jobs\bc367467-ef86-43d2-a937-46ba2d4cc524_v0\sqlmanaged.h:line 1924

那我做错了什么?我该如何远程调试它?

谢谢!

不幸的是,本地 运行 不强制执行内存分配,因此您必须自己在本地顶点调试中检查内存。

查看上面的代码,我发现您正在将 XML 个文档加载到 DOM。请注意,XML DOM 可以将字符串表示形式的数据大小爆炸到 10 倍或更多(我作为常驻 SQL [的时候见过 2 到 12 XML大师)。

今天每个 UDO 只能获得 1/2 GB 的 RAM 来玩。所以我假设您的 XML DOM 文档开始超出此范围。

通常建议您使用 XMLReader 界面(http://usql.io 上的示例中也有一个 reader 提取器)并扫描文档找到您正在寻找的信息。

如果您的文档总是足够小(例如 <20MB),您可能需要确保释放其他文档的内存并一次操作一个文档。

我们确实有计划允许您使用内存需求来注释您的 UDO,但这仍然有点过时。