2

次のコードを最適化するにはどうすればよいですか。現在、100Kを超えるレコードのプールから800以上のレコードを取得してループし、レコードごとに6つのフィールドを返します(追加のフィールドごとに約20秒追加)。

<cfset dllPath="C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.DirectoryServices.dll" />
<cfset LDAPPath="LDAP://" & arguments.searchPath />
<cfset theLookUp=CreateObject(".NET","System.DirectoryServices.DirectoryEntry", dllPath).init(LDAPPath) />
<cfset theSearch=CreateObject(".NET","System.DirectoryServices.DirectorySearcher", dllPath).init(theLookUp) />
<cfset theSearch.Set_Filter(arguments.theFilter) />
<cfset theObject = theSearch.FindAll() />

<cfloop index="row" from="#startRow#" to="#endRow#">
   <cfset QueryAddRow(theQuery) />
   <cfloop list="#columnList#" index="col">
     <cfloop from="0" to="#theObject.Get_Item(row).Get_Properties().Get_Item(col).Get_Count()-1#" index="item">
       <cftry>
         <cfset theQuery[col][theQuery.recordCount]=ListAppend(theQuery[col][theQuery.recordCount],theObject.Get_Item(row).Get_Properties().Get_Item(col).Get_Item(item),"|") />
         <cfcatch type="any">
         </cfcatch>
        </cftry>
      </cfloop>
    </cfloop>
  </cfloop>
4

4 に答える 4

2

久しぶりにCFに触れましたが、疑似コードでヒントを出します。1 つには、この式は非常に非効率的です。

#theObject.Get_Item(row).Get_Properties().Get_Item(col).Get_Count()-1#

たとえば、最初の部分 Get_Item(row) を見てみましょう。このコードにより、CF は #columnList# ループの反復ごとに行とそのプロパティを取得します。さらに、columnlist の反復ごとに 2 回実行しています (1 回は for ループで、もう 1 回は内側の cfset です)。考えてみれば、外側のループ (#sfstart# から #cfend まで) の反復ごとに行を取得するだけで済みます。したがって、疑似コードでは次のようにします。

start と end の間の各行

cfset props = #theobject.get_item(行).get_properties()#

#columnlist# の各列

cfset currentcol = #props.getitem(col)#

cfset カウント = #currentcol.getcount() - 1#

0 から #count# までの foreach アイテム

cfset #currentcol.getItem(item)# など...

わかる?ループに入るたびに、そのスコープ (または子スコープ) で再利用されるオブジェクトを変数にキャッシュします。つまり、列ループの反復ごとに 1 回だけ列オブジェクトを取得します。上記で行ったことからわかるように、外側のスコープで定義されたすべての変数は内側のスコープで使用できます。前の行から切り取って貼り付けたくなる気持ちはわかりますが、やめてください。それは結局あなたを傷つけるだけです。

お役に立てれば、

オイシン

于 2008-09-17T16:32:39.580 に答える
2

内側のループの項目のリストはどのくらいの大きさですか?

項目の数が非常に多い場合は、配列への切り替えが高速になることがあります

x0nの提案と一緒にこれを実装しました...

<cfset dllPath="C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.DirectoryServices.dll" />
<cfset LDAPPath="LDAP://" & arguments.searchPath />
<cfset theLookUp=CreateObject(".NET","System.DirectoryServices.DirectoryEntry", dllPath).init(LDAPPath) />
<cfset theSearch=CreateObject(".NET","System.DirectoryServices.DirectorySearcher", dllPath).init(theLookUp) />
<cfset theSearch.Set_Filter(arguments.theFilter) />
<cfset theObject = theSearch.FindAll() />

<cfloop index="row" from="#startRow#" to="#endRow#">

    <cfset Props = theObject.get_item(row).get_properties() />

    <cfset QueryAddRow(theQuery) />

    <cfloop list="#columnList#" index="col">

        <cfset CurrentCol = Props.getItem(col) />

        <cfset ItemArray = ArrayNew(1)/>
        <cfloop from="0" to="#CurrentCol.getcount() - 1#" index="item">
            <cftry>
                <cfset ArrayAppend( ItemArray , CurrentCol.Get_Item(item) )/>
                <cfcatch type="any">
                </cfcatch>
            </cftry>
        </cfloop>
        <cfset theQuery[col][theQuery.recordCount] = ArrayToList( ItemArray , '|' )/>

    </cfloop>

</cfloop>
于 2008-09-17T18:01:25.030 に答える
1

さらに、各ループで cftry ブロックを使用すると、これがかなり遅くなる可能性があります。個々の行が失敗することが予想される場合 (およびその時点から続行する必要がある場合) を除き、プロセス全体に対して 1 つの try/catch ブロックを使用することをお勧めします。トライ/キャッチはコストのかかる操作です。

于 2008-09-17T17:57:35.663 に答える
0

ループ内で非常に多くの評価を行うのをやめ、代わりに変数を使用してカウント、col オブジェクトへのポインターを保持し、クエリ オブジェクトにコミットする準備ができるまでパイプ区切り文字列を保持することをお勧めします。 . リファクタリングを正しく行った場合、以下のコードを使用すると改善に気付くはずです。

<cfloop index="row" from="#startRow#" to="#endRow#">
<cfset QueryAddRow(theQuery) />
<cfloop list="#columnList#" index="col">
    <cfset PipedVals = "">
    <cfset theItem = theObject.Get_Item(row).Get_Properties().Get_Item(col)>
    <cfset ColCount = theItem.Get_Count()-1>
    <cfloop from="0" to="#ColCount#" index="item">
        <cftry>
        <cfset PipedVals = ListAppend(PipedVals,theItem.Get_Item(item),"|")>
        <cfcatch type="any"></cfcatch>
        </cftry>
    </cfloop>
    <cfset QuerySetCell(theQuery,col) = PipedVals>
</cfloop>

于 2008-09-17T18:05:14.693 に答える