0

以下のコードは 5GB のファイルで実行され、99% の CPU を消費します。私が何かひどく間違ったことをしているのか、何か実行時間を改善できるのか知りたかったのです。

2013-04-03 08:54:19,989 INFO [ロガー] 2013-04-03T08:54:19.987-04:00PCMC.common.manage.springUtil<log-message-body><headers><fedDKPLoggingContext id="DKP_DumpDocumentProperties " type="context.generated.FedDKPLoggingContext"><logFilter>7</logFilter><logSeverity>255</logSeverity><schemaType>PCMC.MRP.DocumentMetaData</schemaType><UID>073104c-4e -4ce-bda-694344ee62</UID><consumerSystemId>JTR</consumerSystemId><consumerLogin>jbserviceid</consumerLogin><logLocation>サービスの正常な完了</logLocation></fedDKPLoggingContext></headers><ペイロード>0</ペイロード></ログメッセージ本文>

これは私が使用しているコードです。gz 形式も試しましたが、すべて無駄でした。そして、私はこの awk を bash から以下のコマンドと呼んでいます。

awk -f mytest.awk <(gzip -dc スキャンしたファイル.$yesterday.gz)| gzip > tem.gz

cat mytest.awk
#!/bin/awk -f

function to_ms (time, time_ms, s) {
    split(time, s, /:|\,/ )
    time_ms = (s[1]*3600+s[2]*60+s[3])*1000+s[4]
    #printf ("%s\n", newtime)
    return time_ms
}

{
   stid = gensub(/.*UID&amp;gt;([^&]+).*/,"\\1","")
}

(stid in starttime) {
    etime = to_ms($2)
    endtime[stid] = etime
    docid[stid] = gensub(/.*id="([^""]+).*/,"\\1","")
    consumer[stid]= gensub(/.*schemaType&amp;gt;PNC.([^.]+).*/,"\\1","")
    state[stid]= gensub(/.*lt;logLocation&amp;gt;([^'' ]+).*/,"\\1","")
    next
}

{
    stime = to_ms($2)
    starttime[stid] = stime
    st_hour[stid] = stime/(60*60*1000)
    timestamp[stid] = $1" "$2
}

END {
    print "Document,Consumer,Hour,ResponseTime,Timestamp,State"
    for (x in starttime) {
        for (y in endtime) {
            if (x==y) {
                diff = (endtime[y]-starttime[x])
                st = sprintf("%02d", st_hour[x])
                print docid[y], consumer[y], st":00", diff, timestamp[x], state[y] |"sort -k3"
                delete starttime[x]
                delete endtime[y]
                delete docid[y]
                delete consumer[y]
                delete timestamp[x]
                delete state[y]
            } 
        }
    }
}
4

3 に答える 3

3

セクションでは、アイテムが見つかって配列から削除された場合でも、常に内部ENDを通過します。a を使用して内部ループから飛び出すことをお勧めします。yendtimebreak

一方、(私が見たように)内部ループはまったく必要ありません!連想配列で既知のキーを持つ要素を見つけようとします。

また、見つかったアイテムを削除しないことをお勧めします。連想配列内のアイテムの検索は一定時間で行われます (ハッシュ キー生成アルゴリズムと生成される重複アイテムの数によって異なります)。そのため、そのような配列からアイテムを削除しても必ずしもプロセスが高速化されるわけではありませんが、アイテムの削除は間違いなくそれを遅く。

したがって、これを使用することをお勧めします:

for (x in starttime) {
    if (x in endtime) {
        diff = (endtime[x]-starttime[x])
        st = sprintf("%02d", st_hour[x])
        print docid[x], consumer[x], st":00", diff, timestamp[x], state[x] |"sort -k3"
    }
}

を使用するとさらに多くの CPU リソースが消費されますが、I/O 帯域幅をいくらか節約できます。

于 2013-07-11T11:27:49.647 に答える
3

すべての stid に終了時間が 1 つだけあると仮定すると、開始時間の配列と終了時間の配列を作成して両方をループしないでください。終了時間になったときに stid を処理するだけです。つまり、今日のようにこれではありません:

{ stid = whatever }
stid in starttime {
   populate endtime[stid]
   next
}
{ populate starttime[stid] }
END {
   for (x in starttime) {
      for (y in endtime) {
          if (x == y) {
              stid = x
              process endtime[stid] - starttime[stid]
          }
      }
   }
}

でもこれは:

{ stid = whatever }
stid in starttime {
   process to_ms($2) - starttime[stid]
   delete starttime[stid]
   next
}
{ populate starttime[stid] }

同じ stid を持つ複数のレコードがあり、最初と最後のレコードからタイムスタンプを取得したいなどの理由でそれができない場合は、END セクションのループを変更して、取得した stid だけをループするようにします。 starttime と endtime でこれらの大規模なループ内のすべての stid を見つけようとする代わりに、endtime を取得しました (対応する starttime があることが既にわかっているため)。

{ stid = whatever }
stid in starttime {
   populate endtime[stid]
   next
}
{ populate starttime[stid] }
END {
   for (stid in endtime) {
      process endtime[stid] - starttime[stid]
   }
}

どちらのアプローチでも、パフォーマンスが大幅に向上するはずです。

于 2013-07-11T12:43:08.057 に答える
0

@ Ed、最初のアプローチでは期待した結果が得られません。これがしたことです

# end time and diff 
(stid in starttime) 
{ etime = to_ms($2) 
diff = etime - stime
 print diff,stid 
delete starttime[stid] 
next } 
# Populate starttime
 { 
stime = to_ms($2) 
starttime[stid] = stime 
st_hour[stid] = stime/(60*60*1000)
 }

o/p は、この sud がミリ秒単位で stid で来るままのようなものです。

561849 c858591f-e01b-4407-b9f9-48302b65c383 562740 c858591f-e01b-4407-b9f9-48302b65c383 563629 56c71ef3-d952-4261-9711-16b18a32c6ba 564484 56c71ef3-d952-4261-9711-16b18a32c6ba

于 2013-07-11T15:29:24.360 に答える