Проблема производительности с xalan API

Следующий метод занимает 33 секунды (время выполнения) для выполнения 10000 итераций. CachedXPathAPI взят из org.apache.xpath.CachedXPathAPI. Я использую xalan-2.7.0.jar. Пожалуйста, любой может помочь здесь, как я могу уменьшить время выполнения. Если мы увеличим нагрузку, скажем, на 40000 итераций, то выполнение займет 10 минут. весь метод readXMLData вызывается из цикла for

public static Hashtable<String, NodeList> readXMLData(CachedXPathAPI cashedXPath, org.w3c.dom.Document doc, String nodePath, int nodeInstance) throws Exception
{
    
    Hashtable<String, NodeList> input = null;

    try
    {
        NodeList rowNodes = cashedXPath.selectNodeList(doc, nodePath);
        // NodeList rowNodes = XPathAPI.selectNodeList( doc, nodePath);
        if (rowNodes == null)
            return null;

        if (rowNodes.getLength() <= 0)
            return null;

        Element rowNode = (Element) rowNodes.item(nodeInstance);
        if (rowNode == null)
            return null;

        NodeList rowElements = rowNode.getChildNodes();
        if (rowElements == null)
            return null;

        input = new Hashtable<String, NodeList>();

        for (int elementIndex = 0; elementIndex < rowElements.getLength(); elementIndex++)
        {
            Node rowElement = rowElements.item(elementIndex);

            if (rowElement.getNodeType() == Node.ELEMENT_NODE)
            {
                Element elem = (Element) rowElement;
                String name = elem.getNodeName();

                if (elem.hasChildNodes())
                {
                    NodeList child = elem.getChildNodes();
                    if (child != null)
                    {
                        input.put(name, child);
                    }
                } else if (elem.hasAttributes())
                {
                    input.put(name, (NodeList) rowElement);
                }
            }
        }

        return input;

    } catch (TransformerException ex)
    {
        throw new Exception("readXMLData (TransformerException): " + ex.getMessage());
    } catch (Exception ex)
    {
        throw new Exception("readXMLData (Exception): " + ex.getMessage());
    }
    
}

person Dattatray Satpute    schedule 10.03.2021    source источник
comment
Я ничего не знаю о xalan, но HashTable — очень старый унаследованный класс. Попробуйте заменить его на HashMap и посмотрите, улучшится ли производительность.   -  person k314159    schedule 10.03.2021
comment
привет @ k314159 спасибо за ответ, я проверю ваше предложение и дам вам знать   -  person Dattatray Satpute    schedule 10.03.2021
comment
3,3 миллисекунды на итерацию звучит относительно быстро. Каковы ваши ожидания? 40 000 должны занять 2-3 минуты, если это линейно. Чем еще отличаются ваши два случая? Возврат null кажется мне плохой идеей. Лучше вернуть пустую карту. Почему вы привязываете своего пользователя к HashMap? Верните карту и скройте реализацию. Что для вас здесь делает кэширование XPath? XML будет плохо работать, если вы будете продолжать прыгать вверх и вниз по дереву DOM. Не похоже, что вы здесь делаете.   -  person duffymo    schedule 10.03.2021


Ответы (1)


Во-первых, я бы использовал HashMap - но сделал сигнатуру метода Map‹String, NodeList› (**).

Подпись вашего метода предполагает, что вы можете делать что-то подобное (или, по крайней мере, обрабатывать один и тот же nodePath в цикле снова и снова...

readXMLData(cashedXPath, doc, nodePath, 1);
readXMLData(cashedXPath, doc, nodePath, 2);
readXMLData(cashedXPath, doc, nodePath, 3);
readXMLData(cashedXPath, doc, nodePath, 4);
readXMLData(cashedXPath, doc, nodePath, 5);

ЕСЛИ это так, то первая очевидная вещь заключается в том, что код selectNodeList выполняется без необходимости снова и снова - его нужно запустить только один раз для набора узлов строки с одним и тем же nodePath.

NodeList rowNodes = cashedXPath.selectNodeList(doc, nodePath);

Предположительно, этот вызов должен поразить значительную часть документа — и он оценивает каждое совпадение XPAth, даже если вы используете только первое [поэтому чем больше совпадений в документе, тем расточительнее это].

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

Еще одна альтернатива, которую следует учитывать, - это размер/сколько памяти используется... (**) каждый раз, когда метод обрабатывает rowElements, который он сохраняет на карте, некоторые из этих данных из DOM. Если вы сохраняете то, что возвращается, то вы сохраняете ссылки на эффективные временные структуры данных, поэтому использование памяти увеличивается и увеличивается, и это может вызвать много сбора мусора... Одним из решений может быть увеличение памяти размер, в котором приложение может работать. Другой может заключаться в том, чтобы выяснить, какая из этой DOM вам действительно нужна, и сохранить в ней значения (например, не структуру DOM, а, возможно, листовое содержимое [но не какой-либо из объектов DOM - так что все эта временная структура, связанная с результатом XPath, может быть освобождена (и подвергнута сборке мусора).

person Mr R    schedule 10.03.2021
comment
спасибо за подробное объяснение, я попробую и сообщу вам результат. - person Dattatray Satpute; 10.03.2021
comment
это решило мою проблему спасибо - person Dattatray Satpute; 12.03.2021
comment
Какая часть - XPath.selectNodeList накипь? - person Mr R; 12.03.2021