Почему DOMDocument :: schemaValidate () для одних и тех же файлов XML и XSD иногда имеют время выполнения, значительно превышающее обычное?

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

Максимальное время выполнения 30 секунд превышено в
script_path
онлайн script_line_number

В этой точной строке:

$result = $DOMDocument -> schemaValidate($schemaPath);

$ DOMDocument всегда одинаков. И он ссылается только на части одного и того же XML с идентификатором atrtibutes. Он не имеет какого-либо URL-подобного атрибута, кроме атрибутов Algorithm и xmlns, которые по своей природе не вызывают никаких ресурсов из любого места, и мы говорим о классе PHP DOMDocument и стандартах XML.

$schemaPath всегда один и тот же, и он указывает на локальный XSD-файл сервера, который всегда там, до и после попытки проверки, успешен он или нет. Схема указывает только на другие локальные файлы xsd, расположенные в той же папке, т.е. <xs:include schemaLocation="schema2.xsd"/>

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

Что может быть причиной того, что выполнение метода займет так много времени?

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

Файлы XML и XSD довольно малы, на самом деле для проверки одного и того же XML и XSD обычно требуется менее ~ 0,1 секунды, но очень редко (~ 1 из 1000) время выполнения превышает 30 секунд.


РЕДАКТИРОВАТЬ

Я выделил проблему, поэтому выкладываю образцы.

schema.xsd:

<?xml version="1.0" encoding="ISO-8859-1"?>
<xs:schema targetNamespace="http://www.foo.bar/Car" xmlns:SiiDte="http://www.foo.bar/Car" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:include schemaLocation="schema2.xsd"/>
<xs:import namespace="http://www.w3.org/2000/09/xmldsig#" schemaLocation="xmldsignature_v10.xsd"/><!-- just the standar signature schema -->
<xs:element name="ROOT" type="SiiDte:ROOTDefType"/>
<xs:complexType name="ROOTDefType">
<xs:sequence>
<xs:element name="Element"></xs:element>
<xs:element ref="ds:Signature">
<xs:annotation>
<xs:documentation>Firma Digital sobre Documento</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
<xs:attribute name="version" type="xs:decimal" use="required" fixed="1.0"/>
</xs:complexType>
</xs:schema>

Schema2.xsd:

<xs:schema targetNamespace="http://www.foo.bar/Car" xmlns:ns1="http://www.foo.bar/Car" xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:simpleType name="MOOType">
<xs:restriction base="xs:positiveInteger">
<xs:enumeration value="1"/>
<xs:enumeration value="2"/>
<xs:enumeration value="3"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>

Код:

// ... a bunch of ther code...

$XML =
'<?xml version="1.0"?>
<ROOT xmlns="http://www.foo.bar/Car" version="1.0">
<Element ID="A1">hello</Element>
<Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
<SignedInfo>
<CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
<SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
<Reference URI="#A1">
<DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
<DigestValue>base64string</DigestValue>
</Reference>
</SignedInfo>
<SignatureValue>base64string</SignatureValue>
<KeyInfo>
<KeyValue>
<RSAKeyValue>
<Modulus>base64string</Modulus>
<Exponent>AQAB</Exponent>
</RSAKeyValue>
</KeyValue>
<X509Data>
<X509Certificate>base64string</X509Certificate>
</X509Data>
</KeyInfo>
</Signature>
</ROOT>'
;

$DD = new DOMDocument();
$DD -> loadXML($XML);
$i = 0;

while ($i < 100) {
// ... a bunch of other code...

libxml_use_internal_errors(true);
$old_libxml_disable_entity_loader = libxml_disable_entity_loader(false);        $result = $DD -> schemaValidate(__DIR__ . '/schema.xsd');
libxml_disable_entity_loader($old_libxml_disable_entity_loader); // Se desactiva nuevamente carga de entidades para descartar entidades maliciosas
$i++;
echo str_pad($i, 5) . ($result ? 'true' : 'false') . '<br>';

// ... a bunch of other code...
}

0

Решение

Проблема заключается в том, что весь сценарий достигает отметки 30 секунд, а не только выполнения DOMDocument :: schemaValidate ().

Время выполнения соответствует полному выполнению скрипта, со всеми его включениями и итерациями, если оно есть.

Учтите, что время выполнения не учитывает никакого времени, потраченного вне сценария, такого как потоковые операции, запросы к базе данных и другие. Так, например, сценарий может выглядеть как 1 минута, а на самом деле он занимает всего 15 или 30. См. http://php.net/manual/en/function.set-time-limit.php в котором говорится:

Примечание: функция set_time_limit () и директива конфигурации
max_execution_time влияет только на время выполнения скрипта
сам. Любое время, потраченное на деятельность, которая происходит за пределами исполнения
сценария, таких как системные вызовы с использованием system (), потоковые операции,
запросы к базе данных и т. д. не учитываются при определении максимального
время, когда скрипт был запущен. Это не так в Windows
где измеренное время реально.

Это не :: schemaValidate (), выполнение которого занимает 30 секунд, это полный сценарий. Тогда почему, когда сценарий достигает 30 секунд, ошибка попадает прямо в schemaValidate ()? Поскольку altought :: schemaValidate () это относительно быстрый метод для выполнения, он должен быть самым сложным кодом внутри итерации, поэтому наибольшая вероятность того, что ошибка возникнет при выполнении schemaValidate, после N повторов (в реальном случае N должен быть много).

Таким образом, ответ: :: schemaValidate () потребляет большую часть времени выполнения, поэтому ошибка возникает виртуально всегда, когда выполняется :: schemaValidate ().

-1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]