我正在对基于MS的Web应用程序进行一些集成,这迫使我通过SOAP将数据提取到我的php应用程序,这很好。
我在xml中获得了一个文件系统的结构,我将其转换为一个对象。所有文档都有ID和路径。为了能够将文档放在树视图中,我已经构建了一些方法来通过文件和文件夹结构来计算文档的位置。这工作正常,直到我开始尝试使用大文件列表。
我需要的是比foreach循环更快的方法(或做事方式)。
以下方法是麻烦制造者。
/**
* Find parent id based on path
* @param array $documents
* @param string $parentPath
* @return int
*/
private function getParentId($documents, $parentPath) {
$parentId = 0;
foreach ($documents as $document) {
if ($parentPath == $document->ServerUrl) {
$parentId = $document->ID;
break;
}
}
return $parentId;
}
// With 20 documents nested in different folders this method renders in 0.00033712387084961
// With 9000 documents nested in different folders it takes 60 seconds
发送给对象的数组如下所示
Array
(
[0] => testprojectDocumentLibraryObject Object
(
[ParentID] => 0
[Level] => 1
[ParentPath] => /Shared Documents
[ID] => 163
[GUID] => 505d70ea-51d7-4ef0-bf79-8e912553249e
[DocIcon] =>
[FileType] =>
[Title] => Folder1
[BaseName] => Folder1
[LinkFilename] => Folder1
[ContentType] => Folder
[FileSizeDisplay] =>
[_UIVersionString] => 1.0
[ServerUrl] => /Shared Documents/Folder1
[EncodedAbsUrl] => http://dev1.example.com/Shared%20Documents/Folder1
[Created] => 2011-10-08 20:57:47
[Modified] => 2011-10-08 20:57:47
[ModifiedBy] =>
[CreatedBy] =>
[_ModerationStatus] => 0
[WorkflowVersion] => 1
)
...
这里有一个更大的数据阵列示例 http://www.trikks.com/files/testprojectDocumentLibraryObject.txt
感谢您的帮助!
=== UPDATE ===
为了说明不同东西的时间,我添加了这部分。
现在,这是一个自定义属性动作,我正在描述,其他的东西已经有所优化。从WCF服务发送的数据是压缩和编码的比率10:1(如10mb未压缩:压缩1mb)。
当前优先级是优化自定义属性部分,其中getParentId方法占用99%的执行时间!
答案 0 :(得分:3)
使用XMLReader或expat而不是simplexml可能会看到更快的结果。这两个都按顺序提供了xml,并且不会将整个文档存储在内存中。
同时确保你有APC扩展,对于实际的循环来说,这是一个很大的区别。实际循环的一些基准测试会很好。
最后,如果你不能让它更快......而不是试图优化读取大型xml文档,你应该研究这种“慢”不是问题的方法。一些想法包括异步过程,适当的缓存等。
修改强>
你实际上是为每个文件调用getParentId吗?这只是发生在我身上。如果你有1000个文件,那么这意味着已经有1000 * 1000个循环。如果确实如此,则需要重写代码,使其成为一个循环。
答案 1 :(得分:1)
你是如何首先填充数组的?也许您可以将项目排列在嵌套数组的层次结构中,其中每个键与路径的一部分相关。
e.g。
['Shared Documents']
['Folder1']
['Yet another folder']
['folderA']
['folderB']
然后在您的getParentId()
方法中,提取路径的各个部分,然后搜索该部分数据:
private function getParentId($documents, $parentPath) {
$keys = explode('/', $parentPath);
$docs = $documents;
foreach ($keys as $key) {
if (isset($docs[$key])) {
$docs = $docs[$key];
} else {
return 0;
}
}
foreach $docs as $document) {
if ($parentPath == $document->ServerUrl) {
return $document->ID;
}
}
}
我还没有完全检查过你会做什么,但它可能会帮助你走上一条有用的道路。
编辑:我错过了你最初没有自己填充阵列;但提前做某种索引可能仍然可以节省你的整体时间,特别是如果多次在同一数据上调用getParentId
。
答案 2 :(得分:0)
像往常一样,这是编程设计的问题。从中可以汲取一些教训。
在文件系统中,父文件始终是一个文件夹,为了加快php中的这个过程你可以将所有文件夹放在一个单独的数组中,并将相应的ID作为密钥,并在你想找到父文件时搜索该数组一个文件,而不是搜索整个文件结构数组!
比较原始帖子
中的自定义属性干杯