Nano Hash - криптовалюты, майнинг, программирование

Медленный SelectSingleNode

У меня есть простой структурированный файл XML, например:

<ttest ID="ttest00001", NickName="map00001"/>
<ttest ID="ttest00002", NickName="map00002"/>
<ttest ID="ttest00003", NickName="map00003"/>
<ttest ID="ttest00004", NickName="map00004"/>

..... Размер этого xml-файла может составлять около 2,5 МБ.

В моем исходном коде у меня будет цикл для получения псевдонимов

В каждом цикле у меня есть что-то вроде этого:

nickNameLoopNum = MyXmlDoc.SelectSingleNode("//ttest[@ID=' + testloopNum + "']").Attributes["NickName"].Value

Эта одна строка будет стоить мне от 30 до 40 миллисекунд.

Я искал некоторые старые статьи (датированные 2002 годом), в которых говорилось, что использование какого-то скомпилированного «xpath» может помочь в ситуации, но это было 5 лет назад. Интересно, есть ли современная практика, чтобы сделать это быстрее? (Я использую .NET 3.5)


  • Прежде чем предоставить решение - какова цель цикла? Вы пытаетесь просто получить список всех псевдонимов? Все никнеймы узлов, которые имеют ID=ttest*? Вместо того, чтобы тратить 30/40 мс на SelectSingleNode, мы могли бы выполнить их все в одном вызове, но я не знаю, какова ваша цель. 22.12.2008

Ответы:


1

Использование аббревиатуры "//" в выражении XPath приводит к большой неэффективности, поскольку приводит к поиску по всему XML-документу. Повторное использование '//' увеличивает эту неэффективность.

Одним из эффективных решений этой проблемы является получение всех узлов атрибутов "NickName" путем вычисления всего одного выражения XPath:

ttest/@NickName

где узел контекста является родителем всех элементов "ttest".

Код C# будет выглядеть следующим образом:

    int n = 15;
    XmlDocument doc = new XmlDocument();
    doc.Load("MyFile.xml");

    XmlNodeList nodeList;
    XmlNode top = doc.DocumentElement;
    nodeList =
        top.SelectNodes("ttest/@NickName");

    // Get the N-th NickName, can be done in a loop for
    // all n in a range

    string nickName = nodeList[n].Value;

Здесь мы предполагаем, что элементы «ttest» являются дочерними элементами верхнего элемента документа xml.

Подводя итог, представлено эффективное решение, которое оценивает выражение XPath только один раз и помещает все результаты в удобный объект IEnumerable (который можно использовать как массив) для доступа к любому требуемому элементу за O(c) времени.

22.12.2008
  • проверьте мой ответ и проверьте код самостоятельно. Вы будете удивлены. 07.05.2010
  • @argatha: Я нигде не говорил, что сразу выбрать атрибуты быстрее, просто быстрее выбрать только необходимые узлы, чем сканировать все дерево. Если все дерево состоит только из узлов, которые мы хотим выбрать, то мы можем выбрать любой способ. Однако на практике во многих случаях XML-документ содержит много больших поддеревьев, которые вообще не содержат ни одного из наших узлов. Протестируйте эти случаи и будьте честны. 07.05.2010

  • 2

    Вы уже используете XPath ("//ttest..."), и это самый медленный способ доступа к узлам документа, поскольку синтаксис "//" просматривает весь документ.

    попробуй как-нибудь...

    foreach (XMLNode node in MyXmlDoc.ChildNodes) {
        ...
    }
    

    вместо этого не требуется xpath, и он должен быть быстрее. (неявное предположение, что это «плоский» xml-файл без вложенности. Если это так, вы скоро будете повторяться, мой мальчик).

    22.12.2008

    3

    В ответ Дмитрию

    На самом деле... выбор всего узла выполняется быстрее, чем выбор только атрибутов.

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

    поместите это в цикл из 10000 итераций и поменяйте местами комментарии, чтобы проверить каждый способ.

     //XmlNodeList nodeList = document.SelectNodes("test/@NickName");
                XmlNodeList nodeList = document.SelectNodes("test");
                foreach (XmlNode node in nodeList)
                {
                    //string nickName = node.Value;
                    string nickName = ((XmlAttribute)node.Attributes.GetNamedItem("NickName")).Value;
    
                }

    Нелогично, я знаю, но.... нужно мерить!!

    07.05.2010

    4

    В этом случае вы можете захотеть прочитать псевдонимы в файле XML в массив (если ваши идентификаторы тестов действительно представляют собой просто последовательные целые числа) или словарь (если нет) заранее, а затем использовать его для поиска каждого псевдонима, а не пытаться сделать кучу запросов XPath. Таким образом, вы, вероятно, получите гораздо лучшую производительность при поиске.

    Изменить: что-то вроде этого (псевдокод)

    var nicknames = new Dictionary<string, string>();
    
    foreach (XmlNode node in MyXmlDoc.ChildNodes)
    {
        if (node is XmlElement)
        {
            nicknames.Add(node.Attributes["ID"], node.Attributes["NickName"]);
        }
    }
    
    ...
    
    nickNameLoopNum = nicknames[testLoopNum];
    
    22.12.2008
    Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..