XPath против DeSerialization: какой из них лучше по производительности для операций чтения

Я передаю небольшие (2–10 КБ) XML-документы в качестве входных данных в службу WCF. теперь у меня есть два варианта чтения значений данных из входящего XML

  1. Десериализация в строго типизированный объект и использование свойств объекта для доступа к значениям
  2. использовать XPath для доступа к значениям

какой подход быстрее? некоторая статистика, подтверждающая ваш ответ, была бы замечательной.

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
10
0
4 694
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Есть третий вариант - придерживаться XML, но запрашивать любой XML API, который вы используете, например LINQ to XML делает запросы относительно простыми в коде.

Вы уже преобразовали текст в XML-документ?

Вы уверены, что это действительно серьезное узкое место в вашем коде? (например, если вы затем разговариваете с базой данных, не беспокойтесь об этом для начала - сначала просто заставьте ее работать самым простым способом)

Всегда ли запросы одинаковы или они каким-то образом динамичны?

У вас есть испытательный стенд с реалистичными сообщениями и запросами? В противном случае он вам понадобится, чтобы оценить любые ответы, приведенные здесь, с данными ваш. Если вы это сделаете, я бы ожидал, что будет достаточно легко попробовать это самостоятельно :)

Спасибо, Джон,> Вы уже разобрали текст в XML-документ? да, я получаю XMLDocument в качестве входных данных> Всегда ли запросы одинаковы или они каким-то образом динамичны? запросы всегда одинаковы. У меня нет реальных данных для тестирования, пока достаточно приблизительного представления

usman shaheen 10.11.2008 15:51

Я предлагаю вам написать его сейчас самым простым способом (возможно, XPath) и измерить время, затраченное на запрос, по сравнению с производительностью всего запроса. Если эта доля когда-либо станет значительной, вернитесь к этому вопросу.

Jon Skeet 10.11.2008 15:55
Ответ принят как подходящий

Я бы десериализовал это.

Если вы используете xpath, вы все равно десериализуете (или «загрузите») его в XmlDocument или что-то еще. Таким образом, оба решения используют десериализацию времени. После этого xpath будет медленнее из-за времени, затраченного на синтаксический анализ этой строки, разрешение имен, выполнение функций и т. д. Кроме того, если вы выберете xpath, вы не получите безопасности типов. Ваш компилятор не может проверить синтаксис xpath за вас.

Если вы используете XmlSerializer и классы, вы получаете статическую типизацию. Действительно быстрый доступ к вашим данным, и если вы хотите запросить их с помощью xpath, все еще есть способы сделать это.

Кроме того, я хотел бы сказать, что ваш код, вероятно, будет легче понять с помощью классов.

Единственный недостаток заключается в том, что xml должен постоянно соответствовать одной и той же схеме, но в вашем случае это может не быть реальной проблемой.

Я надеюсь, что вы простите отсутствие статистики, я считаю аргументы достаточно сильными без примеров. Если вы хотите получить окончательный ответ, попробуйте оба варианта и держите секундомер наготове.

Это был не тот вариант использования, который упоминался в запросе, но когда я сериализовал / десериализовал огромные объемы данных около 600 МБ, я оценил использование IXmlSerializableAttribute.

Rudolf Dvoracek 05.02.2015 13:28

Вот 4 случая, все время в тиках и размещениях:

  • XmlSerializer (самый медленный 4-й)
  • Реализация IXmlSerializable (3-й)
  • Ручная прокатка (на заказ) (1-й)
  • XElement (2-й)

Образец объекта был прочитан 1000 раз.

Вам должно быть все равно? В большинстве случаев используйте сериализаторы по умолчанию, встроенные в .net. Нет необходимости отклоняться, и это даст минимальный объем кода. Этого должно быть более чем достаточно, они должны обеспечивать безопасность типов и позволять себе делать более значимые вещи со своим временем. В некоторых случаях XElement может быть полезен, если вы хотите выделить определенные элементы данных из большой XML-структуры, но даже в этом случае эти элементы следует поместить в строго типизированный DTO. Но имейте в виду, что все методы очень быстрые. Я лично сериализовал чрезвычайно широкую и глубокую объектную модель (более 400 классов) всего за несколько миллисекунд. Для небольших и тривиальных объектов время отклика составляет менее миллисекунд. Разогрев XMLSerializer происходит медленнее, чем у других, но можно смягчить его с помощью SGEN или выполнения некоторой инициализации при запуске.

Детали и код ...

Сериализатор Xml

[Serializable]
    public class FoobarXml
    {
        public string Name { get; set; }
        public int Age { get; set; }
        public bool IsContent { get; set; }

        [XmlElement(DataType = "date")]
        public DateTime BirthDay { get; set; }
    }

Первый раз: 2448965

Среднее значение 1000 при чтении: 245

IXmlSerializable

 public class FoobarIXml : IXmlSerializable
    {
        public string Name { get; set; }
        public int Age { get; set; }
        public bool IsContent { get; set; }
        public DateTime BirthDay { get; set; }

        public XmlSchema GetSchema()
        {
            return null;
        }

        public void ReadXml(XmlReader reader)
        {
            reader.MoveToContent();
            var isEmptyElement = reader.IsEmptyElement;
            reader.ReadStartElement();
            if (!isEmptyElement)
            {
                Name = reader.ReadElementString("Name");

                int intResult;
                var success = int.TryParse(reader.ReadElementString("Age"), out intResult);
                if (success)
                {
                    Age = intResult;
                }

                bool boolResult;
                success = bool.TryParse(reader.ReadElementString("IsContent"), out boolResult);
                if (success)
                {
                    IsContent = boolResult;
                }
                DateTime dateTimeResult;
                success = DateTime.TryParseExact(reader.ReadElementString("BirthDay"), "yyyy-MM-dd", null,
                    DateTimeStyles.None, out dateTimeResult);
                if (success)
                {
                    BirthDay = dateTimeResult;
                }
                reader.ReadEndElement(); //Must Do
            }
        }

        public void WriteXml(XmlWriter writer)
        {
            writer.WriteElementString("Name", Name);
            writer.WriteElementString("Age", Age.ToString());
            writer.WriteElementString("IsContent", IsContent.ToString());
            writer.WriteElementString("BirthDay", BirthDay.ToString("yyyy-MM-dd"));
        }
    }
}

Первый раз: 2051813

Среднее значение 1000 при чтении: 208

Ручная прокатка

 public class FoobarHandRolled
    {
        public FoobarHandRolled(string name, int age, bool isContent, DateTime birthDay)
        {
            Name = name;
            Age = age;
            IsContent = isContent;
            BirthDay = birthDay;
        }

        public FoobarHandRolled(string xml)
        {
            if (string.IsNullOrWhiteSpace(xml))
            {
                return;
            }

            SetName(xml);
            SetAge(xml);
            SetIsContent(xml);
            SetBirthday(xml);
        }

        public string Name { get; set; }
        public int Age { get; set; }
        public bool IsContent { get; set; }
        public DateTime BirthDay { get; set; }

        /// <summary>
        ///     Takes this object and creates an XML representation.
        /// </summary>
        /// <returns>An XML string that represents this object.</returns>
        public override string ToString()
        {
            var builder = new StringBuilder();
            builder.Append("<FoobarHandRolled>");

            if (!string.IsNullOrWhiteSpace(Name))
            {
                builder.Append("<Name>" + Name + "</Name>");
            }

            builder.Append("<Age>" + Age + "</Age>");
            builder.Append("<IsContent>" + IsContent + "</IsContent>");
            builder.Append("<BirthDay>" + BirthDay.ToString("yyyy-MM-dd") + "</BirthDay>");
            builder.Append("</FoobarHandRolled>");

            return builder.ToString();
        }

        private void SetName(string xml)
        {
            Name = GetSubString(xml, "<Name>", "</Name>");
        }

        private void SetAge(string xml)
        {
            var ageString = GetSubString(xml, "<Age>", "</Age>");
            int result;
            var success = int.TryParse(ageString, out result);
            if (success)
            {
                Age = result;
            }
        }

        private void SetIsContent(string xml)
        {
            var isContentString = GetSubString(xml, "<IsContent>", "</IsContent>");
            bool result;
            var success = bool.TryParse(isContentString, out result);
            if (success)
            {
                IsContent = result;
            }
        }

        private void SetBirthday(string xml)
        {
            var dateString = GetSubString(xml, "<BirthDay>", "</BirthDay>");
            DateTime result;
            var success = DateTime.TryParseExact(dateString, "yyyy-MM-dd", null, DateTimeStyles.None, out result);
            if (success)
            {
                BirthDay = result;
            }
        }

        private string GetSubString(string xml, string startTag, string endTag)
        {
            var startIndex = xml.IndexOf(startTag, StringComparison.Ordinal);
            if (startIndex < 0)
            {
                return null;
            }

            startIndex = startIndex + startTag.Length;

            var endIndex = xml.IndexOf(endTag, StringComparison.Ordinal);
            if (endIndex < 0)
            {
                return null;
            }

            return xml.Substring(startIndex, endIndex - startIndex);
        }
    }

Первый раз: 161105

1000 Среднее значение при чтении: 29

XElement

        var xDoc = XElement.Parse(xml);

        var nameElement = xDoc.Element("Name");
        var ageElement = xDoc.Element("Age");
        var isContentElement = xDoc.Element("IsContent");
        var birthDayElement = xDoc.Element("BirthDay");

        string name = null;
        if (nameElement != null)
        {
            name = nameElement.Value;
        }
        var age = 0;
        if (ageElement != null)
        {
            age = int.Parse(ageElement.Value);
        }
        var isContent = false;
        if (isContentElement != null)
        {
            isContent = bool.Parse(isContentElement.Value);
        }
        var birthDay = new DateTime();
        if (birthDayElement != null)
        {
            birthDay = DateTime.ParseExact(birthDayElement.Value, "yyyy-MM-dd", CultureInfo.InvariantCulture);
        }

Первый раз: 247024

1000 Среднее значение при чтении: 113

Другие вопросы по теме