【问题标题】:Web API performance issues with large dynamic XML大型动态 XML 的 Web API 性能问题
【发布时间】:2015-03-11 17:55:48
【问题描述】:

我创建了一个 WebAPI sql 接口,以便开发用户可以通过 RESTful 接口动态查询数据库。小查询速度很快,但当大查询出现时,就会出现严重的延迟问题,尤其是在同时进行多个调用时。我已经对此进行了性能分析,绝大多数处理都是在线完成的:

var xe = reader.ReadOuterXml();

客户端期望 XML 文本字符串,所以我尝试只执行 ExecuteReader,但结果以 2033 字节块返回,这似乎更慢,这是不幸的,因为在 SQL Server Management Studio 中运行此查询( 'For XML Auto')几乎是即时的。

我正在测试 16MB 的 XML 响应,但它们的响应超过 150MB - 200MB。

如何优化它以更好地处理这些大型响应?代码如下:

public XElement AdHockSelect([FromBody] XElement valueElement, string connectionStringName, string database)
{
    try
    {
        string rawConnectionString = ConfigurationManager.ConnectionStrings[connectionStringName].ConnectionString;
        string sqlconnectionstring = string.Format(rawConnectionString, database);
        using (SqlConnection sqlConnection = new SqlConnection(sqlconnectionstring))
        {
            string[] sqlComandTexts = valueElement.Value.Trim().Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
            string sqlQueryText = "";

            foreach (var sqlComandText in sqlComandTexts)
            {
                sqlQueryText += sqlComandText + "  for xml auto;";
            }

            sqlConnection.Open();
            SqlCommand sqlCommand = new SqlCommand(sqlQueryText, sqlConnection);

            using (XmlReader reader = sqlCommand.ExecuteXmlReader())
            {
                XElement xd = new XElement(new XElement("Response"));

                if (reader.EOF)
                {
                    return XElement.Parse("<Response/>");
                }
                else
                {
                    while (!reader.EOF)
                    {
                        if (reader.NodeType == XmlNodeType.Element)
                        {
                            var xe = reader.ReadOuterXml();
                            xd.Add(XElement.Parse(xe));
                        }
                        else
                        {
                            reader.Read();
                        }
                    }
                    return xd;
                }
            }
        }
    }

【问题讨论】:

  • 您的个人资料是否表明reader.ReadOuterXml() 下花费了这么多时间?
  • 更具体地说,ReadOuterXml() 是否需要很长时间,因为每个顶级元素都非常大,所以返回的字符串非常大?
  • 您还应该将SqlCommand 包裹在using()...
  • using (XmlReader reader = sqlCommand.ExecuteXmlReader()) 语句中的代码的用途是什么?看起来好像它创建了一个名为 "Response"XElement,然后在它下面加载 XML。由于格式良好的 XML 文档只有一个根元素,Response 节点将只有一个子节点。那么,while 循环是否必要?
  • @dbc 大部分时间要么被该行占用(46%),要么被 System.Xml.Linq.ni.dll(51.9%)占用服务接收多条sql语句。

标签: c# xml performance asp.net-web-api


【解决方案1】:

与其完全加载每个元素的字符串表示,不如考虑使用XNode.ReadFrom() 将XML 直接流式传输到新的XElement

                if (reader.NodeType == XmlNodeType.Element)
                {
                    var element = XNode.ReadFrom(reader) as XElement;
                    if (element != null)
                        xd.Add(element);
                }
                else
                {
                    reader.Read();
                }

这将比使用ReadOuterXml() 更简单,后者使用临时XmlWriter 将输入流中的XML 复制到输出StringWriter。但是,如果不知道您在ReadOuterXml() 下的时间都花在了哪些地方,我无法预测这种改进是否会很大。

【讨论】:

  • 这在我的测试中提高了大约 40% 的性能。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-01-29
  • 1970-01-01
  • 2016-11-04
  • 1970-01-01
  • 2013-05-09
  • 2019-06-29
  • 2018-09-24
相关资源
最近更新 更多