简体   繁体   English

为什么相同XML和XSD文件上的DOMDocument :: schemaValidate()有时执行时间比平时高得多?

[英]Why DOMDocument::schemaValidate() over the same XML and XSD files have sometimes a execution time dramatically higher than usual?

It is extrange that a default class method fails that way, sometimes, even when the arguments passed to the method are the same that usualy takes a fraction of second. 有时,即使传递给该方法的参数与通常花费一秒钟的时间相同,缺省类方法有时也会失败。

Maximum execution time of 30 seconds exceeded in script_path on line script_line_number script_line_number行的script_path中的最大执行时间超过30秒

In that exact line: 在该行中:

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

$DOMDocument is always the same. $ DOMDocument始终相同。 And it only references parts of the same XML with ID atrtibutes. 而且它仅引用ID属性为相同XML的部分。 It does not have any URL like attribute, besides Algorith and xmlns ones, which by nature does not call anyresource from anywhere, and we are talking about DOMDocument class of PHP and the XML starndards. 除了Algorith和xmlns之外,它没有任何类似URL的属性,这些属性本质上不会从任何地方调用anyresource,我们正在谈论PHP的DOMDocument类和XML starndards。

$schemaPath is always the same, and it is pointing to a server local XSD file, which is always there, before, and after the validation attempt, either it is successful or not. $schemaPath始终相同,并且指向服务器本地XSD文件,该文件在验证尝试之前和之后始终存在,无论成功与否,该文件都始终存在。 The schema is only pointing to other local xsd files, located in the same folder ie <xs:include schemaLocation="schema2.xsd"/> 该模式仅指向位于同一文件夹中的其他本地xsd文件,即<xs:include schemaLocation="schema2.xsd"/>

The only possible answer I can think of, is that the XSD file is located by the method but for some reason it cannot be read, because the disc is busy. 我能想到的唯一可能的答案是,通过该方法可以找到XSD文件,但是由于光盘繁忙,由于某种原因它无法读取。

What could be causing the execution of the method take so long? 是什么导致方法执行时间太长?

What measures should be taken to prevent the error to happen besides increasing the maximum execution time limit of PHP? 除了增加PHP的最大执行时间限制外,还应采取什么措施防止错误发生?

The XML and the XSD files are pretty small, in fact the exact same XML and XSD usually takes less than ~ 0.1 seconds to validate, but a very few times (~ 1 out of 1000) the execution time exeeds 30 seconds. XML和XSD文件非常小,实际上,完全相同的XML和XSD通常花费不到0.1秒的时间来进行验证,但是执行时间却只有极短的时间(每1000个中有1个)需要30秒。


EDIT 编辑

I isolated the problem so I post a samples. 我隔离了问题,因此发布了样本。

Schema.xsd: 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: 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>

Code: 码:

// ... 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...
}

The problem is that the whole script is reaching the 30 seconds mark, not a DOMDocument::schemaValidate() execution alone. 问题在于整个脚本已达到30秒标记,而不是仅执行DOMDocument :: schemaValidate()。

The execution time corresponds to the full script executing, with all its includes and iterations in case it has. 执行时间对应于完整脚本的执行时间,包括所有脚本的包含和迭代。

Consider the execution time does not count any time spent outside the script, such as in stream operations, database queries, amongst others. 考虑执行时间不计算脚本,外面花费任何时候如流操作,数据库查询,等等。 So for example the script may look as taking 1 minut when in reality it is taking only 15 or 30. See http://php.net/manual/en/function.set-time-limit.php which states: 因此,例如,该脚本看起来好像只占用了1分钟,而实际上只占用了15或30。请参阅http://php.net/manual/en/function.set-time-limit.php ,其中指出:

Note: The set_time_limit() function and the configuration directive max_execution_time only affect the execution time of the script itself. 注意:set_time_limit()函数和配置指令max_execution_time仅影响脚本本身的执行时间。 Any time spent on activity that happens outside the execution of the script such as system calls using system(), stream operations, database queries, etc. is not included when determining the maximum time that the script has been running. 确定脚本已运行的最大时间时,不包括执行脚本之外发生的活动上的任何时间,例如使用system()进行系统调用,流操作,数据库查询等。 This is not true on Windows where the measured time is real. 在测量的时间是真实的Windows上不是这样。

It is not ::schemaValidate() which is taking 30 seconds to execute, it is the full script. 这不是::这是采取30秒执行schemaValidate(),它是完整的脚本。 Then why once the script reach 30 seconds the error falls just inside schemaValidate()? 那么,为什么脚本一旦达到30秒,错误便落在schemaValidate()内部? Because altought ::schemaValidate() it is a relatively fast method to execute, it must be the most complex code inside the iteration, hence the biggest chance is the error falls when schemaValidate is executing, after N repetitions (in the real case N must be a lot). 因为altought :: schemaValidate()是一种执行起来相对较快的方法,因此它必须是迭代中最复杂的代码,因此,最大的机会是在执行N次重复后,schemaValidate执行时错误下降了(在实际情况下,N必须很多)。

So the answer is ::schemaValidate() is consuming most of the execution time, hence the error ocurs virtualy always when ::schemaValidate() is executing. 因此,答案是:: schemaValidate()占用了大部分执行时间,因此,在:: schemaValidate()执行时,错误总是在虚拟上发生。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM