いくつかの Common Lisp コードを最適化する助けを借りることができます。ログ ファイルからデータをクエリしようとしています。14.5k 行を超える行から最初の 50 行を引き出すのに 1 秒以上かかります。それを推定すると、ログ ファイルからデータを読み取るだけで 5 分近くかかることになります。さらに、ファイル全体が 14MB しかない場合、現在の実装では最初の 50 行で最大 50MB が割り当てられます。これで行きたいのは、データを 1 回読み取り、最小数のメモリ割り当てで解析することです。
私が目にしているパフォーマンス ヒットは、私のコードが原因であることを知っています。頭を悩ませているのは、発生している問題を最小限に抑えるためにコードをリファクタリングする方法です。WITH-INPUT-FROM-STRING を使用してストリームとして文字列にアクセスしようとしましたが、パフォーマンスは目立って変化しませんでした。
これは IIS ログであるため、一貫した構造になります。最初の 2 つのフィールドは日付と時刻です。必要に応じてデータの範囲を制限できるように、これを解析して数値にします。その後、ほとんどのフィールドは可変サイズになりますが、すべてスペースで区切られます。
マイ コードを使用: 8 つの使用可能な CPU コアで実行するのに 1,138,000 マイクロ秒 (1.138000 秒) かかりました。その期間中、1,138,807 マイクロ秒 (1.138807 秒) がユーザー モードで費やされ、0 マイクロ秒 (0.000000 秒) がシステム モードで費やされ、19,004 マイクロ秒 (0.019004 秒) が GC で費やされました。49,249,040 バイトのメモリが割り当てられています。
マイ コードなし: 8 つの使用可能な CPU コアで実行するのに 64,000 マイクロ秒 (0.064000 秒) かかりました。その期間中、62,401 マイクロ秒 (0.062401 秒) がユーザー モードで費やされ、0 マイクロ秒 (0.000000 秒) がシステム モードで費やされ、834,512 バイトのメモリが割り当てられました。
(defun read-date-time (hit)
(let ((date-time (chronicity:parse (subseq hit 0 20))))
(encode-universal-time (chronicity:sec-of date-time)
(chronicity:minute-of date-time)
(chronicity:hour-of date-time)
(chronicity:day-of date-time)
(chronicity:month-of date-time)
(chronicity:year-of date-time))))
(defun parse-hit (hit)
(unless (eq hit :eof)
(cons (read-date-time hit)
(split-sequence:split-sequence #\Space (subseq hit 20)))))
(time (gzip-stream:with-open-gzip-file (ins "C:\\temp\\test.log.gz")
(read-line ins nil :eof)
(loop for i upto 50
do (parse-hit (read-line ins nil :eof)))))
私の最初の試みは非常に素朴なアプローチであり、コードを改善できる可能性があることを認識しているため、何らかの方向性を求めています。チュートリアルがこの質問に答えるより適切な方法である場合は、リンクを投稿してください。楽しむ