3

サーバーPoVから複雑なWebアプリケーションのプロファイルを作成したいと思います。

上記のウィキペディアのリンクとStackOverflowprofilingタグの説明によると、プロファイリング(その形式の1つ)とは、アプリケーションのAPI /コンポーネントのリスト(またはグラフィック表現)を取得することを意味します。実行時にそれ。

従来の1プログラム/1言語とは異なり、Webサーバーアプリケーションは次のようになる可能性があることに注意してください。

  • 複数のマシンに分散
  • さまざまなコンポーネントがさまざまな言語で記述されている場合があります
  • さまざまなコンポーネントがさまざまなOS上で実行されている可能性があります。

したがって、従来の「プロファイラーを使用するだけ」の回答は、この問題に簡単に適用できません。

私は探していません:

  • さまざまなログ分析ツール(アナログなど)によって提供されるような粗いパフォーマンス統計
  • GoogleのPagespeedやYahoo!などのツールによって提示されるようなクライアント側のページごとのパフォーマンス統計 Y!遅い、ウォーターフォール図、およびブラウザーコンポーネントのロード時間)

代わりに、古典的なプロファイラースタイルのレポートを探しています。

  • 通話数
  • 通話時間

Webアプリケーションのサーバー側で、function / API/component-nameによって。

結論として、問題は次のとおりです。

多層、マルチプラットフォーム、分散型Webアプリケーションをどのようにプロファイリングできますか?

自由ソフトウェアベースのソリューションが非常に好まれます。

私はしばらくの間ウェブで解決策を探していましたが、かなり高価な商用製品を除いて、私のニーズに合う満足のいくものを見つけることができませんでした。結局、私は弾丸を噛み、問題について考え、自由に共有したい自分自身の解決策を書きました。

このプラクティスはSOで奨励されているため、私は自分のソリューションを投稿しています

このソリューションは完璧にはほど遠いです。たとえば、非常に高レベル(個々のURL)であるため、すべてのユースケースに適しているとは限りません。それにもかかわらず、それは私のWebアプリがどこで時間を費やしているのかを理解しようとするのに非常に役立ちました。

オープンソースと知識の共有の精神で、私は他の人からの、特に優れたアプローチと解決策を歓迎します。

4

2 に答える 2

3

従来のプロファイラーがどのように機能するかを考えると、この課題に対する一般的な自由ソフトウェアソリューションを思い付くのは簡単なはずです。

問題を2つの部分に分けてみましょう。

  • データの収集
  • データの提示

データの収集

Webアプリケーションを個々の構成要素(API、関数)に分割し、これらの各部分が完了するまでにかかる時間を測定できると仮定します。各部分は1日に数千回呼び出されるため、複数のホストで1日程度にわたってこのデータを収集できます。1日が終わると、かなり大きくて関連性の高いデータセットができあがります。

エピファニー#1: 「関数」を「 URL 」に置き換えます。既存のWebログは「それ」です。必要なデータはすでにあります。

  • Web APIの各部分は、リクエストURLによって定義されます(場合によってはいくつかのパラメーターを使用)
  • ラウンドトリップ時間(多くの場合マイクロ秒単位)が各行に表示されますこのデータを使用して、1日(週、月)に相当する行があります。

したがって、Webアプリケーションの分散されたすべての部分の標準Webログにアクセスできれば、問題の1つ(データの収集)は解決されます。

データの提示

これでビッグデータセットができましたが、それでも本当の洞察はありません。どうすれば洞察を得ることができますか?

Epiphany#2:(複数の)Webサーバーログを直接視覚化します。

写真は1000語の価値があります。どの写真を使用できますか?

数十万または数百万行の複数のWebサーバーログを短い要約に凝縮する必要があります。これにより、パフォーマンスに関するほとんどのストーリーがわかります。言い換えると、目標はプロファイラーのようなレポートを生成することです。さらに良いのは、Webログから直接グラフィカルなプロファイラーレポートを生成することです。

マップできると想像してみてください。

  • 1次元への通話遅延
  • 別のディメンションへの呼び出しの数、および
  • 色に対する関数の恒等式(基本的には3次元)

そのような図の1つ:APIによるレイテンシーのスタック密度チャートを以下に示します(関数名は説明のために作成されました)。

チャート:

1000ワードストーリー:APIによるWebアプリケーションのスタックレイテンシー分散

この例からのいくつかの観察

  • アプリケーションには、3つの根本的に異なる「世界」を表す3つのモーダル分布があります。
  • 最速の応答は、約300マイクロ秒の遅延を中心としています。これらの応答は、ニスキャッシュからのものです
  • 2番目に速く、平均で0.01秒弱かかりますが、中間層のWebアプリケーション(Apache / Tomcat)によって提供されるさまざまなAPIからのものです。
  • 最も遅い応答は、約0.1秒を中心とし、応答に数秒かかる場合があり、SQLデータベースへのラウンドトリップが含まれます。

アプリケーションでキャッシュ効果がどれほど劇的になるかを確認できます(x軸はlog10スケールであることに注意してください)。

どのAPIが高速か低速かを具体的に確認できるため、何に焦点を当てるべきかがわかります。

毎日最も頻繁に呼び出されるAPIを確認できます。また、それらのいくつかはめったに呼び出されないため、チャート上でそれらの色を確認することさえ困難であることがわかります。

どうやってするの?

最初のステップは、必要なサブセットデータを前処理してログから抽出することです。ここでは、複数のログに対するUnixの「cut」のような簡単なユーティリティで十分な場合があります。また、複数の類似したURLを、「登録」や「購入」などの関数/APIを説明する短い文字列に折りたたむ必要がある場合もあります。ロードバランサーによって生成されたマルチホスト統合ログビューがある場合、このタスクの方が簡単な場合があります。API(URL)の名前とそのレイテンシーのみを抽出するため、TABで区切られた1組の列を持つ1つの大きなファイルになります。

*API_Name   Latency_in_microSecs*


func_01    32734
func_01    32851
func_06    598452
...
func_11    232734

次に、結果のデータペアに対して以下のRスクリプトを実行して、必要なグラフを作成します(Hadley Wickhamのすばらしいggplot2ライブラリを使用)。 出来上がり!

チャートを生成するためのコード

最後に、API +LatencyTSVデータファイルからグラフを作成するコードは次のとおりです。

#!/usr/bin/Rscript --vanilla
#
# Generate stacked chart of API latencies by API from a TSV data-set
#
# ariel faigon - Dec 2012
#
.libPaths(c('~/local/lib/R',
         '/usr/lib/R/library',
         '/usr/lib/R/site-library'
))

suppressPackageStartupMessages(library(ggplot2))
# grid lib needed for 'unit()':
suppressPackageStartupMessages(library(grid))

#
# Constants: width, height, resolution, font-colors and styles
# Adapt to taste
#
wh.ratio = 2
WIDTH = 8
HEIGHT = WIDTH / wh.ratio
DPI = 200
FONTSIZE = 11
MyGray = gray(0.5)

title.theme   = element_text(family="FreeSans", face="bold.italic",
                        size=FONTSIZE)
x.label.theme = element_text(family="FreeSans", face="bold.italic",
                        size=FONTSIZE-1, vjust=-0.1)
y.label.theme = element_text(family="FreeSans", face="bold.italic",
                       size=FONTSIZE-1, angle=90, vjust=0.2)
x.axis.theme  = element_text(family="FreeSans", face="bold",
                        size=FONTSIZE-1, colour=MyGray)
y.axis.theme  = element_text(family="FreeSans", face="bold",
                        size=FONTSIZE-1, colour=MyGray)

#
# Function generating well-spaced & well-labeled y-axis (count) breaks
#
yscale_breaks <- function(from.to) {
    from <- 0
    to <- from.to[2]
    # round to 10 ceiling
    to <- ceiling(to / 10.0) * 10
    # Count major breaks on 10^N boundaries, include the 0
    n.maj = 1 + ceiling(log(to) / log(10))
    # if major breaks are too few, add minor-breaks half-way between them
    n.breaks <- ifelse(n.maj < 5, max(5, n.maj*2+1), n.maj)
    breaks <- as.integer(seq(from, to, length.out=n.breaks))
    breaks
}

#
# -- main
#

# -- process the command line args:  [tsv_file [png_file]]
#    (use defaults if they aren't provided)
#
argv <- commandArgs(trailingOnly = TRUE)
if (is.null(argv) || (length(argv) < 1)) {
    argv <- c(Sys.glob('*api-lat.tsv')[1])
}
tsvfile <- argv[1]
stopifnot(! is.na(tsvfile))
pngfile <- ifelse(is.na(argv[2]), paste(tsvfile, '.png', sep=''), argv[2])

# -- Read the data from the TSV file into an internal data.frame d
d <- read.csv(tsvfile, sep='\t', head=F)

# -- Give each data column a human readable name
names(d) <- c('API', 'Latency')

#
# -- Convert microseconds Latency (our weblog resolution) to seconds
#
d <- transform(d, Latency=Latency/1e6)

#
# -- Trim the latency axis:
#       Drop the few 0.001% extreme-slowest outliers on the right
#       to prevent them from pushing the bulk of the data to the left
Max.Lat <- quantile(d$Latency, probs=0.99999)
d <- subset(d, Latency < Max.Lat)

#
# -- API factor pruning
#       Drop rows where the APIs is less than small % of total calls
#
Rare.APIs.pct <- 0.001
if (Rare.APIs.pct > 0.0) {
    d.N <- nrow(d)
    API.counts <- table(d$API)
    d <- transform(d, CallPct=100.0*API.counts[d$API]/d.N)
    d <- d[d$CallPct > Rare.APIs.pct, ]
    d.N.new <- nrow(d)
}

#
# -- Adjust legend item-height &font-size
#    to the number of distinct APIs we have
#
API.count <- nlevels(as.factor(d$API))
Legend.LineSize <- ifelse(API.count < 20, 1.0, 20.0/API.count)
Legend.FontSize <- max(6, as.integer(Legend.LineSize * (FONTSIZE - 1)))
legend.theme  = element_text(family="FreeSans", face="bold.italic",
                        size=Legend.FontSize,
                        colour=gray(0.3))


# -- set latency (X-axis) breaks and labels (s.b made more generic)
lat.breaks <- c(0.00001, 0.0001, 0.001, 0.01, 0.1, 1, 10)
lat.labels <- sprintf("%g", lat.breaks)
#
# -- Generate the chart using ggplot
#
p <- ggplot(data=d, aes(x=Latency, y=..count../1000.0, group=API, fill=API)) +
   geom_bar(binwidth=0.01) +
      scale_x_log10(breaks=lat.breaks, labels=lat.labels) +
      scale_y_continuous(breaks=yscale_breaks) +
      ggtitle('APIs Calls & Latency Distribution') +
      xlab('Latency in seconds - log(10) scale') +
      ylab('Call count (in 1000s)') +
      theme(
            plot.title=title.theme,
            axis.title.y=y.label.theme,
            axis.title.x=x.label.theme,
            axis.text.x=x.axis.theme,
            axis.text.y=y.axis.theme,
            legend.text=legend.theme,
            legend.key.height=unit(Legend.LineSize, "line")
      )

#
# -- Save the plot into the png file
#
ggsave(p, file=pngfile, width=WIDTH, height=HEIGHT, dpi=DPI)
于 2013-03-02T20:10:03.517 に答える
2

「昔の」プロファイリングの実践に関するあなたの議論は真実です。常に抱えていた小さな問題が1つだけあります。

  • おもちゃではないソフトウェアでは、何かが見つかるかもしれませんが、多くの理由であまり見つかりません。

より高いパフォーマンスの機会については、それらが見つからなくても、ソフトウェアは壊れないので、存在しないふりをすることができます. つまり、別の方法が試行され、それらが見つかるまでです。

統計では、これはタイプ 2 エラー (偽陰性) と呼ばれます。機会はそこにありますが、あなたはそれを見つけられませんでした。それが意味することは、誰かそれを見つける方法を知っていれば、彼らは大いに勝つだろうということです. これについては、おそらくあなたが知りたいと思っていた以上のものがあります。

したがって、Web アプリで同じ種類のもの (呼び出し回数、時間測定など) を見ている場合、同じ種類の非結果よりも優れた結果になる可能性はありません。

私は Web アプリには興味がありませんが、何年も前にプロトコル ベースのファクトリー オートメーション アプリでかなりの量のパフォーマンス チューニングを行いました。ロギング手法を使用しました。簡単だったとは言いませんが、うまくいきました。似たようなことをしている人々がここにいて、彼らはウォーターフォール チャートと呼んでいるものを使用しています。基本的な考え方は、広いネットをキャストして多くの測定値を取得するのではなく、トランザクションの単一の論理スレッドをトレースして、必要のない遅延が発生している場所を分析することです。

結果があなたの求めているものなら、私はその考え方を見下します。

于 2013-03-03T01:26:38.023 に答える