2011-10-09 129 views
2

我正在對基於MS的Web應用程序進行一些整合,這迫使我通過SOAP將數據提取到我的PHP應用程序,這很好。在PHP foreach循環中需要更多速度

我在一個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 ===

爲了說明不同的東西需要我增加了這部分的時間。

  1. 包在8.5031080245972秒下載
  2. 包在1.2838368415833秒
  3. 包在0.051079988479614秒解壓在3.8216209411621秒組織
  4. 列表數據
  5. 標準特性填補了0.46236896514893秒
  6. 定製解碼物業填寫40.856066942215秒
  7. 總計:本頁面創建時間55.231353998184秒!

現在,這是一個自定義屬性操作,即時消息描述,其他的東西已經有所優化。從WCF服務發送的數據是壓縮和編碼比例10:1(如10mb未壓縮:1mb壓縮)。

當前的優先事項是優化自定義屬性部分,其中getParentId方法佔用99%的執行時間!

+0

需要更快的速度?要麼得到更好的硬件,要麼切換到更快的語言。考慮到PHP是[最慢的語言之一](http://shootout.alioth.debian.org/u32/which-programming-languages-are-fastest.php),這不應該是一項艱鉅的任務。 – NullUserException

+0

好吧,我同意你的意見。但在這種情況下,我沒有選擇。具有相同規格的服務器上的C#中的「相同」方法在不到2秒的時間內運行相同的數據。 –

+0

聽起來不太可能。 PHP循環並不是很快,但是你的做法並不多。 SOAP解包和對象樹生成的可能性比較慢。 - 如果你多次運行你的函數,並且忘記在你的問題中提及關鍵細節,建議單獨構建一個單獨的 - > ServerURL到 - > ID數組映射*,然後用它來代替。 – mario

回答

0

像往常一樣,這是一個編程設計問題。從中可以學到一些經驗教訓。

在一個文件系統中,父文件總是一個文件夾,爲了加快php中的這個過程,你可以把所有的文件夾放在一個單獨的數組中,並將其相應的ID作爲關鍵字,並在你想查找而不是搜索整個文件結構數組!

  1. 包在6.9351849555969秒下載
  2. 包在1.2411289215088秒
  3. 包在0.04874587059021秒解壓在3.7993721961975秒組織
  4. 列表數據
  5. 標準特性填補了0.4488160610199秒
  6. 定製解碼物業填寫0.15889382362366秒
  7. 本頁面創建於11.578738212585秒!

比較由一個自定義屬性從我原來的職位

乾杯

3

通過使用XMLReader或expat而不是simplexml,您可能會看到更快的結果。這兩種方法都需要順序執行xml,並且不會將整個文檔存儲在內存中。

此外,請確保您有APC擴展,對於實際循環來說,這是一個很大的區別。在實際循環的一些基準將會很好。

最後,如果你不能讓速度更快......而不是試圖優化閱讀大型xml文檔,你應該研究一下這種「緩慢」不成問題的方法。一些想法包括一個異步過程,適當的緩存等。

編輯

你實際調用getParentId每一個文件?這發生在我身上。如果你有1000個文件,那麼這意味着已經有1000 * 1000個循環。如果確實如此,則需要重寫代碼以使其成爲單個循環。

+0

很好的答案。 –

+0

謝謝,這很聰明。但是當im在那個部分時,xml已經在可以使用的對象中了。你所描述的是我在帖子底部添加的流程中的第四點。這是我的第二優先考慮,但現在不是真正的問題。感謝您的建議,但+1! –

+0

以字節爲單位的實際xml文檔有多大? – Evert

1

你是如何填充陣列的第一個地方?也許你可以將這些項目排列在嵌套數組的層次結構中,其中每個鍵與路徑的一部分相關。

例如

['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