0

VB.netで書かれた関数が1つあります。コードは次のようになります。

For rowIndex As Integer = 0 To nRows - 1
        Dim max As Integer = -1
        Dim arrTemp() As String
        arrTemp = Nothing

        For columnIndex As Integer = 0 To nCols - 1
            If IsNumeric(arrTranspose(rowIndex, columnIndex)) Then
                Dim iVal As Integer = arrTranspose(rowIndex, columnIndex)

                If iVal < 0 Then
                    iVal = Math.Abs(iVal)
                End If

                If max < iVal Then
                    max = iVal
                    ReDim Preserve arrTemp(max)
                End If
                arrTemp(iVal) += String.Format("{0},", (columnIndex + 1))
            End If
        Next
        arrRespondentIDs(rowIndex) = arrTemp
    Next

nRow = 210 nCols = 64772

上記のコードでは、最初のループの実行に4〜5分かかります。調査して観察しました。その後、IsNumeric関数のため、さらに時間がかかります。これについてはよくわかりません。

コードのどの部分がパフォーマンスの問題を引き起こしているのか、誰でも考えられますか?あなたのアイデアを共有してください。

ありがとう、Mohmedsadiq。

4

1 に答える 1

2

O(n ^ 2)の複雑さでコードを記述しましたが、これは適切にスケーリングされません。見た目からは、それについてできることはあまりありません。内部ループ内のコードを改善する具体的な方法:

  • 多くのコーナーケースを処理するため、非常に高価な関数であるIsNumeric()を使用します。金額を表す値のように、負の金額の括弧や$や"USD"などの単位などが含まれる場合があります。しかし、実際には整数に変換できる値にのみ関心があります。次に行うことは、IsNumeric()関数がそれを通知しないことです。確かに、そのような金額はうまく変換されません。したがって、Integer.TryParse()のように、より正確な変換関数を使用します。

  • テストは無意味です、If iVal < 0 ThenMath.Abs​​()関数はすでにそれをします。直接呼んでください。

  • ReDim Preserve arrTemp(max)は恐ろしく高価であり、プロファイルセッションでポップアウトしなかったことは非常に驚くべきことです。アレイを何度も再割り当てしてコピーします。配列の代わりにList(Of String)を使用する必要があります。特に、この種の費用を最小限に抑えるのが得意です。

  • そのarrTemp(iVal) += String.Format("{0},", (columnIndex + 1))声明は高価であり、そもそもあなたをこの問題に巻き込んだのと同じ種類の罪を犯します。データを文字列として保存することは非常に賢明ではありません。これは非常に不器用なデータ形式であり、永久に変換し直す必要があり、CPUサイクルを焼き付けて利益を得ることができません。文字列を気にするのは、人間がデータを見るときだけです。これは、コード内の異なる場所でのみ発生します。データがバイナリ形式で保持されている場合、プログラムは最も効率的に動作します。ここにあいまいさはありません。columnIndexは常に整数です。前の箇条書きと組み合わせると、arrTempは文字列の配列ではなく、List(Of Integer)である必要があります。

コードの残りの部分でデータ型として文字列を削除することにより、このコードを改善するための追加の方法を見つけてください。ObjectでさえStringよりも優れています。

于 2012-08-11T14:27:48.370 に答える