- 浏览: 486138 次
- 性别:
- 来自: 北京
-
文章分类
最新评论
-
alvin198761:
renzhengzhi 写道我参与过12306余票查询系统的开 ...
别给12306 辩解了 -
renzhengzhi:
我参与过12306余票查询系统的开发,用户请求被前面3层缓存拦 ...
别给12306 辩解了 -
renzhengzhi:
写的很好。
JAVA线程dump的分析 -
liyonghui160com:
说好的附件呢
分布式服务框架 Zookeeper -- 管理分布式环境中的数据 -
ghpaas:
orbeon作为xforms标准的实现,不论其设计器还是运行时 ...
XForms 1.1 中文翻译—第1章 关于XForms标准
上个月 我介绍了如何用 AspectWerkz 框架实现一个基本的性能跟踪方面(aspect)。这个月我将进一步发展这个方面, 首先增加一些方便的功能,然后将它用于分析一个复杂的真实世界代码 —— Apache Axis Web 服务框架。您将看到我用这种面向方面的方法进行性能跟踪的好处和局限性,最后我的看法是,进行一般性的日志和跟踪是面向方面编程(AOP)通常可以发挥作用的地方。 在深入 Axis 之前,需要讨论另一个问题。在上个月的性能跟踪方面以及在更早的一篇 关于 Java 编程动态性 的文章中(请参阅 参考资料),我使用了 方法计时信息来分析应用程序性能问题。我个人认为这种方法在某些情况下非常方便,但是, 为了使对它的介绍尽可能地全面,还需要讨论一些副作用的问题。我将在本文的第一部分中讨论这些问题。 我的性能跟踪方面的主要目的是监视程序的执行,并给出执行时间从上到下的视图( 与通常用 profiler 得到的从下到上的视图正好相反)。要真正有效地使用它,需要 对时间是如何测量的多少有一些了解。 Java 编程语言有一个计时方法,从早期版本起它就是标准 API 的一部分。 这个方法是 另一个局限是在方法定义中的基本时间单位。当 Java 平台第一次开始使用时,一毫秒 仍然是相当短的时间间隔(特别是对于解释语言)。今天,随着 CPU 时钟速度比第一次发布 Java 平台时快了近一百倍,一毫秒已经成了相对长的一段时间。 除了 使用 清单 2 展示在我的笔记本计算机(有较慢的 1GHz PIIIm,运行 Mandrake Linux 10.0)上用 JDK 1.4.2 运行这个程序的结果。结果显示,在这个例子上, 在 JDK 5.0 中,Sun 增加了另一个方法 很容易修改 清单 1 代码以用 从清单 3 的结果中可以看出, 将 上个月 的性能跟踪方面改为使用 基本原理仍然与 上个月 一样,但是这段代码 添加了几个警告。除了使用 增加的构造函数代码使用 AspectWerkz 2.0 定义的一个签名来访问上下文信息,这些信息包括 为方面定义的所有参数。我将在用到这些参数时,展示如何在 XML 配置文件中定义 它们。 在实际的 最后,我改变了跟踪输出的格式以使它更具可读性。这段代码不用空格缩进,而用连字号代替空格, 当方法调用是在嵌套的最深层时,它将在前面打印出星号而不是用于显示从嵌套级中退出的小于号(<)。 我在 Linux 上运行 AspectWerkz 确实遇到过几个奇怪的小问题。首先,提供的 shell 脚本 在我的系统上不运行,因为它们使用 DOS 格式的行结束。我改了行结束后,它们可以在 1.0 和 2.0 RCX 版本上工作,但是不能工作在 1.1 上(我在这里不深究这个问题)。 希望这个问题在 2.0 版本时能修复。 其次,我遇到了 AspectWerkz 1.0 与 2.0 RC3 之间的兼容性问题,这看来是特定于 Linux 的,它使我在使用 AspectWerkz 2.0 时,不得不在 classpath 中加入 Axis 所引用 的所有 JAR 文件,即使其中一些 JAR(包括 Servlet API 定义)通常在客户机上是不需要的。 AspectWerkz 开发人员在 Windows 上再现不了这个问题,但是如果在 Linux 上使用 AspectWerkz 2.0,那么您可能也会遇到同样的问题。 准备好了 清单 4 中新的和改进过的性能跟踪方面,就需要找一个目标应用程序 用这个方面显微镜进行检查。我选择了 Apache Axis Web 服务框架,运行一个客户机应用程序以避免让服务器代码复杂化。因为我的主要工作是 Web 服务,因此 Axis 很适合。我曾经至少花了几周时间分析过 Axis 代码,因此我对它的结构相当熟悉 —— 不过我也还记得第一次试图跟踪这些代码采用的通常很费解的路径时有多么 痛苦。 为照顾不与 Web 服务打交道的读者,下面是它的简单介绍。 Axis 是 Java Web 服务的 JAX-RPC 标准的实现。它支持客户机应用程序(它以 XML 消息的 格式发出请求)和服务器端应用程序(它对收到的请求生成 XML 响应消息), 大多数 Axis 代码是两端都使用的。由于 Web 消息的特性,框架的工作过程在高层上是很清楚的。 在客户机端,可以归纳如下:接受来自用户代码的请求的数据、发送请求并等待响应、 从响应中提取数据、最后将数据提交给用户代码。但是在 Axis 框架中这个过程的实际发生 细节却很容易让人迷惑。 我已经有一个在前面的 Web 服务性能测试中使用的 Axis 客户机应用程序(请参阅 参考资料 中的链接),因此在本月的文章中,我将对这个客户机应用程序使用性能跟踪方面。 我还要运行对应的 Axis 服务器应用程序,这样客户机就可以有响应,但是不会包括在性能跟踪中。 这个应用程序的实际目的是从服务器上提取地震数据库中的信息。 初步观察 Axis 执行时,我想看看基本时间分布,这可让我了解代码的哪些部分执行的时间最长 (当然还有到达这些部分的路径)。要完成这个任务,我使用的方面配置将告诉它截获我的应用程序代码和 Axis 代码 中的所有方法调用,但是最大嵌套深度只到七 —— 这样我就不会被大量细节所淹没。 清单 5 给出了我将使用的 AspectWerkz 配置: 上个月 文章的读者应当熟悉清单 5 配置中的大部分内容。所使用的配置的主要区别是我使用了更复杂的表达式来定义我的方面的切入点,并且增加了一个参数值来定义最大嵌套深度。在我以前的配置中, 使用了 在测试 Axis 时,我通常多次穿越(请求-响应交换)代码,这样,第一次穿越将处理 初始化,而后面的穿越就可以全速运行。在用性能跟踪方面测试时,我只使用两次穿越, 并且我将只显示第二次穿越的输出。清单 6 给出了使用 清单 5 配置 时,通过 AspectWerkz 运行这个程序的输出。注意,即使使用 我的客户机测试程序将结果打印到控制台,这样,它们就与清单 6 中的性能跟踪信息混在一起。忽略客户机程序输出后,跟踪信息明白地告诉我时间花在什么地方了 —— 总时间的 90% 多花在 通过比较 清单 6 的最后一行中显示的请求的总执行时间(2203 毫秒)与不通过 AspectWerkz 运行的请求 的计时,我可以大致了解到我的监视对程序增加了多少开销。在本例中,大约是 1 倍 —— 我直接运行这个程序的时间一般是在 1000 到 1100 毫秒这个范围。 为什么这个程序使用了方面后,它的运行速度只有一半了呢?有两个不同的因素 增加了开销。第一个是由 AspectWerk 的字节码操作增加的,这使它可以在每当目标方法被 调用时调用我的方面。第二个是由计时代码和向控制台输出跟踪所增加的。 注释掉除了 如果更好地选择切入点方法 —— 比如取消对只返回一个字段值 的简单 get 方法的截获,本来是可以减少这些开销的。这些简单的 get 方法可能构成了大量的方法调用,因此消除它们 有可能极大地降低开销。不幸的是,对于 Axis 代码,不能根据方法名统一地做到这一点,因为它遵守 标准 Java 语言的对简单和复杂的操作都使用 get 格式的名字的习惯做法。 AspectWerkz 在使用方面时,可以容易地区分简单的方法与至少进行一些处理的方法, 但是没有办法告诉它从切入点中排除这些方法。因此,我保留截获开销,除非我想要减少切入点中类的数量,或者 列出要从切入点中排除的各个方法。这两种方法都没有吸引力,因此我就留着这些开销,并观察 在我的方法垮掉之前能得到多少有用的信息。 请参阅前面的 清单 6,总时间的 90% 以上都花在了 清单 7 配置保留了与以前一样的切入点定义,但是为方面增加了 一个触发器方法,并将最大嵌套深度减小到 5。清单 8 给出了这个跟踪配置 生成的输出(不带客户机程序输出,那些没有改变): 这个更详细的执行时间视图开始展示一些有用的细节了。我现在可以看到对 我要进一步深入挖掘,进入 清单 10 显示了清单 9 配置生成的输出的一个示例。完整的输出非常长,且 有很多重复,因此我只包括了一个示例。在这里分析 Axis XML 消息处理的细节,以及 各个方法调用所用的时间并没有多大意义 —— 它只是在处理消息的各个组件时所做 的调用的数量叠加。 清单 10 展示了这个性能跟踪方面的作用的局限性。它可以很快地让您了解 应用程序中最花费时间的部分,这很不错,但是在实际找出哪些代码运行得慢并且加以改进 这方面不是很有用。不过,后一个问题用常规的执行 profiler 可以很好地解决,因此 不会错过什么。性能跟踪和执行 profiler 可以成为分析和改进应用程序性能的有用工具。 本月专栏展示了跟踪型的方面如何提供关于程序执行的有用信息。它们可以取代嵌入到程序代码 中的日志语句吗?在我看来,还不能全部取代,因为日志通常用于记录开发人员或者用户感兴趣的特定信息, 这些信息只能在方法的逻辑中访问(在这些地方不能定义切入点)。出于性能考虑,禁止日志后, 甚至可能不会生成这些信息。我在本月专栏中分析的 Axis 代码包含许多提供了这种特殊信息的日志语句。 其他类型的日志语句由简单的方法进入和退出信息组成。用一个可以在运行时激活的外部方面 可以容易地替代它们。这个方面可以设计为使用嵌入日志代码所使用的同样日志框架, 这样合在一起的输出就可以给出程序执行的综合视图。我不准备写一个这样的方面,但是希望 本专栏的这些文章可以使您更清楚如何在自己的应用程序中使用这种方法。 下个月我将分析 ASM 字节码操作框架。ASM 是我在关于 classworking 的以前的文章中讨论过的 Javassist 和 BCEL 框架的另一种选择。 它提出了一些令人印象深刻的性能要求(claim),因此我将分析性能和易用性,重写了为 Javassist 和 BCEL 所写的一些例子以在 ASM 中使用。java.lang.System.currentTimeMillis()
,它返回从 UTC 1970 年 1 月 1 日午夜开始经过的毫秒数。这个方法非常有用,特别 是它在各个版本的 Java 平台上都有。因此,在 上个月 我的 初始方面演示代码中,我使用了它。不过,currentTimeMillis()
也有 一些缺点。currentTimeMillis()
的一个问题是,它虽然是以毫秒计数返回 时间,但是不能保证返回的计数的粒度或精度。在一些系统上,时间是真正的毫 秒计数,大约每一毫秒改变一次。在另一些系统上,时间可能每隔 10 或 20 毫秒才变一 次,因此每一次的精度都可能变化。currentTimeMillis()
的这些问题, 还有另一个使用任何类型的计时器方法监视程序执行都会有的问题。这个问题 是计时器方法本身 —— 可能要深入操作系统才能访问计时器 —— 这增加了一些开销, 如果计时器方法开销过大(或者方法调用过于频繁),那么就会严重扭曲计时测量。 为了明智地使用我们的性能跟踪方面,我需要至少大体知道计时器方法调用增加 了多少开销。currentTimeMillis()
到底有多大问题?为了澄清这一点,我编写了 一个程序进行一些测试。这个程序如清单 1 所示,通过重复调用这个方法直到返回值改变, 以一种非常简单的方式检查 currentTimeMillis()
的 粒度、精度和开销。改变的幅度告诉我计时器的 粒度,两次改变之间的调用次数可以得出每次调用的开销,而改变幅度的一致性和改变 之间的调用次数让我可以检查精度。
清单 1. currentTimeMillis() 粒度
public class MilliGran
{
// round value to a single digit after decimal point
private static String roundOneDecimal(double value) {
int whole = (int)value;
return whole + "." + (int)((value-whole)*10.0);
}
// print average and deviation with lead text
private static void print(String lead, double sum,
double ssqr, int reps) {
double mean = sum / reps;
double stddev = Math.sqrt(ssqr/reps-mean*mean);
System.out.println(lead + roundOneDecimal(mean) +
", with standard deviation " + roundOneDecimal(stddev));
}
public static void main(String[] argv) {
// get control values from command line
int reps = Integer.parseInt(argv[0]);
int sets = Integer.parseInt(argv[1]);
// loop until time rolls over
long start = System.currentTimeMillis();
long last;
while ((last = System.currentTimeMillis()) == start);
// loop for count of sets specified
int[] diffs = new int[reps];
for (int i = 0; i < sets; i++) {
double lsum = 0.0;
double lsumsq = 0.0;
double dsum = 0.0;
double dsumsq = 0.0;
for (int j = 0; j < reps; j++) {
// count loops until result changes
int loop = 0;
last = System.currentTimeMillis();
long now;
do {
loop++;
now = System.currentTimeMillis();
} while (now == last);
// accumulate statistics information
lsum += loop;
lsumsq += loop*loop;
int diff = (int)(now-last);
dsum += diff;
dsumsq += diff*diff;
diffs[j] = diff;
}
// print results for set
System.out.println("Set " + i + " results:");
print(" Average time change ", dsum, dsumsq, reps);
print(" Average calls before change ", lsum, lsumsq, reps);
System.out.println(" Average time per call " +
roundOneDecimal(dsum / lsum * 1000000.0) + " nanoseconds");
System.out.print(" Differences:");
for (int j = 0; j < reps; j++) {
System.out.print(" " + diffs[j]);
}
System.out.println();
}
}
}
currentTimeMillis()
的时间改变总是一个毫秒,调用这个 方法的开销平均只有 3 毫秒。因为这些值都很一致(在这里是百分之一以内),所以至少 可以合理地假定计时器值是足够精确的。
清单 2. 运行 currentTimeMillis() 测试的结果
[dennis@notebook time]$ java -cp . MilliGran 10 4
Set 0 results:
Average time change 1.0, with standard deviation 0.0
Average calls before change 332.8, with standard deviation 39.4
Average time per call 3004.8 nanoseconds
Differences: 1 1 1 1 1 1 1 1 1 1
Set 1 results:
Average time change 1.0, with standard deviation 0.0
Average calls before change 338.6, with standard deviation 38.7
Average time per call 2953.3 nanoseconds
Differences: 1 1 1 1 1 1 1 1 1 1
Set 2 results:
Average time change 1.0, with standard deviation 0.0
Average calls before change 333.6, with standard deviation 33.5
Average time per call 2996.7 nanoseconds
Differences: 1 1 1 1 1 1 1 1 1 1
Set 3 results:
Average time change 1.0, with standard deviation 0.0
Average calls before change 336.8, with standard deviation 41.4
Average time per call 2969.1 nanoseconds
Differences: 1 1 1 1 1 1 1 1 1 1
java.lang.System.nanoTime()
,它可以提供更好的计时信息。顾名思义,nanoTime()
返回一个以纳秒为单位的时间值, 提供了比 currentTimeMillis()
方法精确一百万倍的精度。即使当今的 大多数系统无法提供纳秒精度的时间,但是实际值应当至少比用老的方法获得的要好得多。nanoTime()
方法代替 currentTimeMillis()
。我在这里就不显示修改后的代码了 (不过它包括在 参考资料 部分中的代码下载中), 但是清单 3 显示了运行修改后的程序的结果,这一次使用了 JDK 5.0:
清单 3. 运行 nanoTime() 测试的结果
[dennis@notebook time]$ java -cp . NanoGran 10 4
Set 0 results:
Average time change 2800.0, with standard deviation 400.0
Average calls before change 1.0, with standard deviation 0.0
Average time per call 2800.0 nanoseconds
Differences: 3000 3000 3000 3000 2000 2000 3000 3000 3000 3000
Set 1 results:
Average time change 2900.0, with standard deviation 300.0
Average calls before change 1.0, with standard deviation 0.0
Average time per call 2900.0 nanoseconds
Differences: 3000 3000 3000 3000 3000 3000 2000 3000 3000 3000
Set 2 results:
Average time change 2700.0, with standard deviation 458.2
Average calls before change 1.0, with standard deviation 0.0
Average time per call 2700.0 nanoseconds
Differences: 2000 3000 3000 2000 3000 3000 3000 3000 3000 2000
Set 3 results:
Average time change 2900.0, with standard deviation 300.0
Average calls before change 1.0, with standard deviation 0.0
Average time per call 2900.0 nanoseconds
Differences: 3000 3000 3000 3000 2000 3000 3000 3000 3000 3000
nanoTime()
方法运行得比 currentTimeMillis()
要稍快一些。但是更重要的是,每次调用后,它返回 不同的时间值,看起来粒度为 1000 纳秒(或者 1 毫秒)。我是怎样知道粒度的?当然从这些结果中不能十分确定,但是对 nanoTime()
的前后两次调用的结果值之差总是 2 或者 3 毫秒这一实事 则很能说明问题。
nanoTime()
很容易。在改的时候,我还做了一些其他改变以改进代码的 易用性,并让测试更灵活。清单 4 给出了相应部分做了修改的代码:
清单 4. 性能跟踪方面代码
public class TraceAspect
{
private static final long DEFAULT_MINIMUM = 1000000;
private final long m_minimumNanoseconds;
private final int m_maximumNesting;
private final String m_triggerClass;
private final String m_triggerName;
private int m_matchDepth;
private int m_nestingDepth;
private ArrayList m_pendingPrints = new ArrayList();
public TraceAspect(AspectContext context) {
// set minimum time value for tracing a method
String value = context.getParameter("minimum-time");
m_minimumNanoseconds = (value == null) ?
DEFAULT_MINIMUM : Long.parseLong(value);
// set maximum depth to be printed
value = context.getParameter("maximum-depth");
m_maximumNesting = (value == null) ?
Integer.MAX_VALUE : Integer.parseInt(value);
// set trigger class and method name if supplied
value = context.getParameter("trigger-method");
if (value == null) {
m_matchDepth = 1;
m_triggerClass = null;
m_triggerName = null;
} else {
int split = value.lastIndexOf('.');
m_triggerClass = value.substring(0, split);
m_triggerName = value.substring(split+1);
}
}
private void indent(int depth) {
for (int i = 0; i < depth; i++) {
System.out.print((i % 2 == 0) ? ' ' : '-');
}
}
private void indent() {
indent(m_nestingDepth);
}
private void printFullMethod(JoinPoint call) {
MethodSignature signature = (MethodSignature)call.getSignature();
System.out.print(signature.getDeclaringType().getName());
System.out.print('.');
System.out.print(signature.getName());
}
public Object trace(JoinPoint join) throws Throwable {
// check for match on trigger
boolean match = false;
MethodSignature signature = (MethodSignature)join.getSignature();
if (signature.getName().equals(m_triggerName)) {
if (signature.getDeclaringType().getName().equals(m_triggerClass)) {
match = true;
m_matchDepth++;
}
}
// check if execution is to be processed
if (m_matchDepth == 0 || m_nestingDepth > m_maximumNesting) {
// skip any timing or printing
return join.proceed();
} else {
// add joinpoint to list pending print
m_pendingPrints.add(join);
m_nestingDepth++;
// time joinpoint execution
long start = System.nanoTime();
Object result = null;
Throwable thrown = null;
try {
result = join.proceed();
} catch (Throwable t) {
thrown = t;
} finally {
// adjust depths
m_nestingDepth--;
if (match) {
m_matchDepth--;
}
// remove joinpoint if still on pending list
// (will always be last in list)
boolean entered = true;
if (m_pendingPrints.size() > 0) {
m_pendingPrints.remove(m_pendingPrints.size()-1);
entered = false;
}
// check if execution time above cutoff
long time = System.nanoTime() - start;
if (time >= m_minimumNanoseconds || thrown != null) {
// print all unprinted "entering" lines
int count = m_pendingPrints.size();
for (int i = 0; i < count; i++) {
// print entering information for nesting call
// (nesting depth based on start of pendings)
indent(m_nestingDepth-count+i);
JoinPoint prior = (JoinPoint)m_pendingPrints.get(i);
System.out.print('>');
printFullMethod(prior);
System.out.println();
}
// clear all pendings now that they're printed
m_pendingPrints.clear();
// print exiting information including time
indent();
System.out.print(entered ? '<' : '*');
printFullMethod(join);
System.out.print(" took ");
long tenthmillis = (time+50000)/100000;
System.out.print(tenthmillis / 10);
System.out.print('.');
System.out.print(tenthmillis % 10);
System.out.print(" ms.");
// append exception information
if (thrown != null) {
System.out.println(" threw " +
thrown.getClass().getName() +
": " + thrown.getMessage());
throw thrown;
} else {
System.out.println();
}
}
}
return result;
}
}
}
nanoTime()
,我还在方面定义中增加了三个可选配置参数。这些参数控制:
trace()
方法开始的地方,我添加了检查触发器方法名与类 匹配的逻辑,如果知道调用不会打印出来,就直接执行 joinpoint 方法调用而不进行计时 (由于触发器方法不在调用的当前嵌套中,或者由于我们已经深入到嵌套中我们不感兴趣的地方)。 我还在基本计时代码中增加了一个 throwable 处理,这样,当方法由于一个抛出而退出而不是正常返回时, 在跟踪中就会加入基本抛出信息。
Linux 上的 AspectWerkz
清单 5. 初步观察的配置
<aspectwerkz>
<system id="AspectWerkzExample">
<package name="com.sosnoski.aspectwerkz">
<aspect class="TraceAspect">
<pointcut name="traceexecution">
execution(* org.apache.axis..*(..)) || execution(* com.sosnoski.seismic..*(..))
</pointcut>
<advice name="trace" type="around" bind-to="traceexecution"/>
<param name="maximum-depth" value="7"/>
</aspect>
</package>
</system>
</aspectwerkz>
pointcut
元素的属性来定义这个表达式,使用更长的 表达式可以更容易地使它成为元素的内容。AspectWerkz 允许互换地使用这两种形式。 切入点表达式表明我希望在 org.apache.axis
和 com.sosnoski.seismic
层次结构中加入包中的所有类中的所有方法调用。nanoTime()
进行计时, 我还是将所有时间值转换为毫秒以保证数字大小适合于打印。
清单 6.初步观察性能跟踪
Running query for date range from 2002-04-02 13:12:53 to 2002-12-15 04:08:40,
longitude range from 40.71031 to 160.91571,
latitude range from -70.6799 to 22.293274,
->com.sosnoski.seismic.axislit.AxisDocLitClient.runQuery
- >com.sosnoski.seismic.axislit.SeismicBindingStub.matchQuakes
- ->org.apache.axis.client.Call.invoke
- - >org.apache.axis.client.Call.invoke
- - ->org.apache.axis.client.Call.invoke
- - - *org.apache.axis.client.Call.invoke took 591.4 ms.
- - - *org.apache.axis.message.RPCElement.getParams took 1447.0 ms.
- - -<org.apache.axis.client.Call.invoke took 2042.0 ms.
- - <org.apache.axis.client.Call.invoke took 2042.9 ms.
- -<org.apache.axis.client.Call.invoke took 2043.1 ms.
- ->org.apache.axis.client.Stub.extractAttachments
- - >org.apache.axis.Message.getAttachments
- - ->org.apache.axis.attachments.AttachmentsImpl.getAttachmentCount
- - - *org.apache.axis.SOAPPart.saveChanges took 155.7 ms.
- - -<org.apache.axis.attachments.AttachmentsImpl.getAttachmentCount took 157.5 ms.
- - <org.apache.axis.Message.getAttachments took 157.7 ms.
- -<org.apache.axis.client.Stub.extractAttachments took 157.9 ms.
- <com.sosnoski.seismic.axislit.SeismicBindingStub.matchQuakes took 2202.4 ms.
-<com.sosnoski.seismic.axislit.AxisDocLitClient.runQuery took 2202.9 ms.
Results from query:
Seismic region New Zealand Region has 1 regions and 2 matching quakes
Seismic region Bismarck and Solomon Islands has 4 regions and 30 matching quakes
Seismic region New Guinea has 9 regions and 55 matching quakes
Seismic region Caroline Islands Area has 2 regions and 8 matching quakes
Seismic region Guan to Japan has 2 regions and 10 matching quakes
Seismic region Taiwan Area has 1 regions and 2 matching quakes
Seismic region Philippine Islands has 5 regions and 22 matching quakes
Seismic region Bornea - Sulawesi has 10 regions and 37 matching quakes
Seismic region Sunda Arc has 12 regions and 49 matching quakes
Seismic region Myanmar and Southeast Asia has 1 regions and 2 matching quakes
Seismic region India - Xizand - Sichuan - Yunnan has 1 regions and 2 matching quakes
Seismic region Indian Ocean has 9 regions and 27 matching quakes
Seismic region Africa has 3 regions and 3 matching quakes
Seismic region Macquarie Loop has 1 regions and 2 matching quakes
Seismic region Andaman Islands to Sumatera has 4 regions and 14 matching quakes
-*com.sosnoski.seismic.axislit.AxisDocLitClient.summarize took 1.7 ms.
Result match count 265 in 2203 ms.
org.apache.axis.client.Call.invoke()
方法上。这个时间的不到 30% 花在用同一个名字调用另一个方法上(或者对同一方法的递归调用 —— 我从跟踪中无法区别),而所有剩下的时间实质上都花在了对org.apache.axis.message.RPCElement.getParams()
方法的调用上。trace()
方法体中 return join.proceed();
以外的所有内容,以便惟一的开销就是截获方法调用所增加的,这样可以比较这两个组件。 结果它只比 清单 6 所显示的全部输出快约 10%, 因此我知道在这里几乎所有开销都是由于调用我的方面所产生的。org.apache.axis.client.Call.invoke()
方法上。它自然成了更详细的性能跟踪的目标。 我将使用清单 7 配置获得更详细的视图:
清单 7. 深入挖掘配置
<aspectwerkz>
<system id="AspectWerkzExample">
<package name="com.sosnoski.aspectwerkz">
<aspect class="TraceAspect">
<pointcut name="traceexecution">
execution(* org.apache.axis..*(..)) || execution(* com.sosnoski.seismic..*(..))
</pointcut>
<advice name="trace" type="around" bind-to="traceexecution"/>
<param name="maximum-depth" value="5"/>
<param name="trigger-method" value="org.apache.axis.client.Call.invoke"/>
</aspect>
</package>
</system>
</aspectwerkz>
清单 8. 深入挖掘跟踪输出
>org.apache.axis.client.Call.invoke
>org.apache.axis.client.Call.invoke
->org.apache.axis.client.Call.invoke
- >org.apache.axis.client.Call.invoke
- ->org.apache.axis.MessageContext.setTargetService
- - *org.apache.axis.AxisEngine.getService took 14.9 ms.
- -<org.apache.axis.MessageContext.setTargetService took 16.7 ms.
- ->org.apache.axis.client.Transport.setupMessageContext
- - *org.apache.axis.transport.http.HTTPTransport.setupMessageContextImpl took 2.8 ms.
- -<org.apache.axis.client.Transport.setupMessageContext took 3.4 ms.
- ->org.apache.axis.message.MessageElement.output
- - *org.apache.axis.message.SOAPEnvelope.outputImpl took 5.8 ms.
- -<org.apache.axis.message.MessageElement.output took 6.5 ms.
- ->org.apache.axis.client.Call.invokeEngine
- - *org.apache.axis.client.AxisClient.invoke took 572.3 ms.
- -<org.apache.axis.client.Call.invokeEngine took 573.4 ms.
- >org.apache.axis.client.Call.invoke took 602.6 ms.
- >org.apache.axis.message.RPCElement.getParams
- ->org.apache.axis.message.RPCElement.deserialize
- - *org.apache.axis.message.MessageElement.publishToHandler took 1447.2 ms.
- -<org.apache.axis.message.RPCElement.deserialize took 1449.0 ms.
- <org.apache.axis.message.RPCElement.getParams took 1449.4 ms.
-<org.apache.axis.client.Call.invoke took 2054.9 ms.
<org.apache.axis.client.Call.invoke took 2057.1 ms.
<org.apache.axis.client.Call.invoke took 2057.4 ms.
org.apache.axis.client.Call.invoke()
最内部的调用是包装了 请求处理的调用,包括对服务器的调用。这个调用在返回之前必须等待服务器响应,因此显然 有大量处理是在跟踪所覆盖的范围之外进行的 —— 所有服务器代码都是在没有 AspectWerkz 的、单独的 JVM 中 运行的。真正的客户机处理负荷出现在 org.apache.axis.message.RPCElement.getParams()
调用中,我可以看到 实质上所有处理时间都花在对 org.apache.axis.message.MessageElement.publishToHandler()
的调用上。org.apache.axis.message.MessageElement.publishToHandler()
方法, 清单 8 输出指出它是大部分客户机处理发生的地方。清单 9 显示了 完成这个任务的一个配置。在这里,我从切入点中去掉了客户机代码,因为对它不再感兴趣了, 我还将加入跟踪的方法调用的最小时间减小到 .4 毫秒(以纳秒表示)。最后,我改变了用来激活对 感兴趣的新方法的跟踪的触发器方法。
清单 9. 二次深入挖掘配置
<aspectwerkz>
<system id="AspectWerkzExample">
<package name="com.sosnoski.aspectwerkz">
<aspect class="TraceAspect">
<pointcut name="traceexecution"
expression="execution(* org.apache.axis..*(..))"/>
<advice name="trace" type="around" bind-to="traceexecution"/>
<param name="minimum-time" value="400000"/>
<param name="maximum-depth" value="5"/>
<param name="trigger-method" value="org.apache.axis.message.MessageElement.publishToHandler"/>
</aspect>
</package>
</system>
</aspectwerkz>
清单 10. 二次深入挖掘跟踪输出
>org.apache.axis.message.MessageElement.publishToHandler
>org.apache.axis.message.SAX2EventRecorder.replay
->org.apache.axis.encoding.DeserializationContext.startElement
- *org.apache.axis.message.RPCHandler.onStartChild took 0.7 ms.
- >org.apache.axis.encoding.ser.BeanDeserializer.startElement
- ->org.apache.axis.encoding.DeserializerImpl.startElement
- - *org.apache.axis.encoding.ser.BeanDeserializer.onStartElement took 12.8 ms.
- -<org.apache.axis.encoding.DeserializerImpl.startElement took 13.1 ms.
- <org.apache.axis.encoding.ser.BeanDeserializer.startElement took 13.1 ms.
-<org.apache.axis.encoding.DeserializationContext.startElement took 15.9 ms.
->org.apache.axis.encoding.DeserializationContext.startElement
- *org.apache.axis.encoding.ser.BeanDeserializer.onStartChild took 0.6 ms.
-<org.apache.axis.encoding.DeserializationContext.startElement took 1.0 ms.
-*org.apache.axis.encoding.DeserializationContext.startElement took 0.6 ms.
-*org.apache.axis.encoding.DeserializationContext.endElement took 0.5 ms.
->org.apache.axis.encoding.DeserializationContext.startElement
- *org.apache.axis.encoding.ser.BeanDeserializer.onStartChild took 0.5 ms.
-<org.apache.axis.encoding.DeserializationContext.startElement took 0.9 ms.
->org.apache.axis.encoding.DeserializationContext.startElement
- >org.apache.axis.encoding.ser.BeanDeserializer.onStartChild
- -*org.apache.axis.encoding.DeserializationContext.getTypeFromAttributes took 1.3 ms.
- <org.apache.axis.encoding.ser.BeanDeserializer.onStartChild took 1.9 ms.
-<org.apache.axis.encoding.DeserializationContext.startElement took 2.5 ms.
-*org.apache.axis.encoding.DeserializationContext.endElement took 0.6 ms.
->org.apache.axis.encoding.DeserializationContext.startElement
- *org.apache.axis.encoding.ser.BeanDeserializer.onStartChild took 0.4 ms.
-<org.apache.axis.encoding.DeserializationContext.startElement took 0.8 ms.
->org.apache.axis.encoding.DeserializationContext.startElement
- >org.apache.axis.encoding.ser.BeanDeserializer.startElement
- ->org.apache.axis.encoding.DeserializerImpl.startElement
- - *org.apache.axis.encoding.ser.BeanDeserializer.onStartElement took 121.8 ms.
- -<org.apache.axis.encoding.DeserializerImpl.startElement took 123.3 ms.
- <org.apache.axis.encoding.ser.BeanDeserializer.startElement took 123.3 ms.
-<org.apache.axis.encoding.DeserializationContext.startElement took 123.9 ms.
->org.apache.axis.encoding.DeserializationContext.endElement
- *org.apache.axis.encoding.DeserializerImpl.endElement took 0.5 ms.
-<org.apache.axis.encoding.DeserializationContext.endElement took 0.8 ms.
...
发表评论
-
Storix简介
2012-03-27 12:10 1074简介 Storix ... -
asa阿萨
2012-03-25 23:58 1阿迪撒旦撒旦 -
适配器布局
2010-10-28 11:23 972网络性能取决于所选的硬件,如机器中的适配器类型和适配器布局 ... -
工作负载管理诊断
2010-07-13 23:15 853工作负载管理仅指评估工作负载的每个组成部分的优先级。 ... -
与磁盘或内存相关的问题
2010-07-13 23:12 886与磁盘或内存相关的问题 正如大部分实内存可用来缓冲文 ... -
在 AIX V5.3 中使用 MALLOCDEBUG 隔离并解决内存泄漏
2010-07-01 15:02 1280引言 在编写应用程序 ... -
分析AIX上的native内存泄露
2010-07-01 14:59 1493Running native profiling on ... -
AIX性能——预处理器和编译器利用
2010-06-27 20:37 1070在指令重新整理中,有几个优化级别给予编译器以不同程度的自由 ... -
AXI性能——系统调整
2010-06-27 20:37 883在有效实现应用程序后,系统总体性能的进一步提高就成了系统调 ... -
AIX性能调整——当前的机器指令
2010-06-27 20:35 916如果未出现 TLB 或高速缓存未命中的情况,绝大多数机器指令都 ... -
可分派线程
2010-06-27 20:33 880当某个线程可分派但不在运行时,它不能完成任何有用的事情。更糟的 ... -
等待线程
2010-06-27 20:31 956无论何时只要执行的程序发出不能立刻满足的请求,例如同步 I ... -
AXI性能调整——中断处理程序
2010-06-27 20:30 1099通知操作系统发生了外部事件的机制是中断当前运行线程并将控制 ... -
AIX性能调整——可执行程序
2010-06-27 20:28 970当请求运行某个程序 ... -
AIX性能调整——硬件层次结构
2010-06-27 20:26 1029通常,从一个硬件级别移动到另一级别所需要的时间主要由较低级 ... -
AIX性能调整——程序执行模型
2010-06-27 20:21 936为了清楚地检查工作负载的性能特征,需要有一个动态而非静态的 ... -
AIX4.3 TL12安装指南
2010-06-18 11:01 1186Installation instructions Te ... -
系统工作负载
2010-05-16 22:40 825系统工作负载的完整准确的定义对于预测或理解它的性能是很关键 ... -
列出可用的软件产品(lslpp 命令)
2010-05-13 09:16 1209要显示关于系统上可用软件产品的信息,请使用 lslpp 命 ... -
列出可用的字体(font 命令)
2010-05-13 09:14 1202要显示可用于显示器的字体列表,请使用 lsfont 命令。 ...
相关推荐
基于万能逼近原理的自适应模糊控制算法在多自由度AUV运动控制中的应用与抗干扰补偿Simulink仿真研究,自适应模糊控制算法的万能逼近原理与多自由度AUV运动控制的抗干扰补偿技术——基于Simulink的仿真研究,万能逼近原理自适应模糊控制算法的多自由度AUV运动控制抗干扰补偿simulink仿真 ,核心关键词:万能逼近原理; 自适应模糊控制算法; 多自由度AUV运动控制; 抗干扰补偿; Simulink仿真。,基于万能逼近的模糊控制算法多自由度AUV抗干扰补偿Simulink仿真
deepseek最新资讯、配置方法、使用技巧,持续更新中
deepseek最新资讯、配置方法、使用技巧,持续更新中
结合扩展卡尔曼滤波与滑模观测器的策略:优化电角度估计,反电势波形逼近完美正弦波,结合扩展卡尔曼滤波与滑模观测器的反电势波形优化:正弦波形展现近乎完美精度,电角度估算与实际应用差异微小,扩展卡尔曼滤波与滑模观测器的结合,反电势波形近乎完美的正弦波形,观测器估算转子电角度与实际电角度相差0.3弧度左右,转速跟随效果较好。 ,核心关键词:扩展卡尔曼滤波; 滑模观测器; 反电势波形; 转子电角度估算; 转速跟随效果。,卡尔曼滑模观测器:优化正弦波转子角度与转速估算
毕业设计_基于springboot+vue的**学生公寓管理系统**【源码+sql+可运行】【**50217**】.zip 全部代码均可运行,亲测可用,尽我所能,为你服务; 1.代码压缩包内容 代码:springboo后端代码+vue前端页面代码; 脚本:数据库SQL脚本 效果图:运行结果请看资源详情效果图 2.环境准备: - JDK1.8+ - maven3.6+ - nodejs14+ - mysql5.6+ - redis 3.技术栈 - 后台:springboot+mybatisPlus+Shiro - 前台:vue+iview+Vuex+Axios - 开发工具: idea、navicate 4.功能列表 - 系统设置:用户管理、角色管理、资源管理、系统日志 - **业务管理:业务管理:公寓信息、房间信息、入住记录、学生信息** 3.运行步骤: 步骤一:修改数据库连接信息(ip、port修改) 步骤二:找到启动类xxxApplication启动 4.若不会,可私信博主!!!
1、文件内容:xorg-x11-server-source-1.20.4-29.el7_9.rpm以及相关依赖 2、文件形式:tar.gz压缩包 3、安装指令: #Step1、解压 tar -zxvf /mnt/data/output/xorg-x11-server-source-1.20.4-29.el7_9.tar.gz #Step2、进入解压后的目录,执行安装 sudo rpm -ivh *.rpm 4、更多资源/技术支持:公众号禅静编程坊
1、文件内容:yum-plugin-ps-1.1.31-54.el7_8.rpm以及相关依赖 2、文件形式:tar.gz压缩包 3、安装指令: #Step1、解压 tar -zxvf /mnt/data/output/yum-plugin-ps-1.1.31-54.el7_8.tar.gz #Step2、进入解压后的目录,执行安装 sudo rpm -ivh *.rpm 4、更多资源/技术支持:公众号禅静编程坊
基于模型预测控制(MPC)的无人船与无人车编队一致性协同控制研究(附原文献),基于模型预测控制(MPC)的无人船与无人车编队一致性协同控制研究(附原文献),无人船编队 无人车编队 MPC 模型预测控制 多智能体协同控制 一致性 MATLAB 无人车 USV 带原文献 ,无人船编队; 无人车编队; MPC 模型预测控制; 多智能体协同控制; 一致性; MATLAB; USV; 原文献,无人系统协同控制:MPC模型预测控制下的多智能体编队与一致性研究(原文献支撑)
4套中级通信工程师综合真题及答案(2019,2020,2021,2023),适用于需要考中级通信工程师的人群
deepseek最新资讯,配置方法,使用技巧,持续更新中
基于matlab的锁相环PLL相位噪声拟合仿真代码集合:多个版本建模与仿真,高质量的锁相环PLL仿真代码集合:Matlab与Simulink建模研究,[1]锁相环 PLL 几个版本的matlab相位噪声拟合仿真代码,质量杠杠的,都是好东西 [2]锁相环matlab建模稳定性仿真,好几个版本 [3]锁相环2.4G小数分频 simulink建模仿真 ,PLL; Matlab相位噪声拟合仿真; Matlab建模稳定性仿真; 锁相环2.4G小数分频Simulink建模仿真,MATLAB仿真系列:锁相环PLL及分频器建模仿真
exceptionLogs.zip
基于光伏微网的经济性与并网负荷波动率双目标优化调度策略:蓄电池与V2G协同管理策略仿真研究,MATLAB下光储充微网结合电动汽车V2G的多目标协同调度策略研究:经济性与并网负荷波动性的对比分析,MATLAB代码:考虑V2G的光储充一体化微网多目标优化调度策略 关键词:光储充微网 电电汽车V2G 多目标优化 蓄电池优化 调度 参考文档:《光伏微网下考虑V2G补偿蓄电池容量的双目标优化调度策略》,已经投稿EI会议,中文说明文档可联系我咨询 仿真平台:MATLAB 平台 优势:代码注释详实,适合参考学习,相关成果已经采用,程序非常精品,请仔细辨识 主要内容:过建立光伏微网中以经济性和并网负荷波动率为双目标的蓄电池和V2G的协同调度模型。 采用粒子群算法,对电网、微网调度中心和电动汽车用户三方在无、无序、转移和调度V2G电动汽车负荷四种运行模式下的经济和安全影响进行对比。 最后,根据算例分析,求解四种模式下两级负荷曲线及经济收益表。 对比分析得出,引入V2G可以替代部分容量的蓄电池,使光伏微网在负荷峰谷平抑、三方经济和安全等方面进一步优化。 求解采用的是PSO算法(粒子群算法),求解效果极
javascript 动态网页设计期末大作业(自己手写的,高分期末作业),含有代码注释,新手也可看懂,个人手打98分项目,导师非常认可的高分项目,毕业设计、期末大作业和课程设计高分必看,下载下来,简单部署,就可以使用。该项目可以直接作为毕设、期末大作业使用,代码都在里面,系统功能完善、界面美观、操作简单、功能齐全、管理便捷,具有很高的实际应用价值,项目都经过严格调试,确保可以运行! javascript 动态网页设计期末大作业(自己手写的,高分期末作业)javascript 动态网页设计期末大作业(自己手写的,高分期末作业)javascript 动态网页设计期末大作业(自己手写的,高分期末作业)javascript 动态网页设计期末大作业(自己手写的,高分期末作业)javascript 动态网页设计期末大作业(自己手写的,高分期末作业)javascript 动态网页设计期末大作业(自己手写的,高分期末作业)javascript 动态网页设计期末大作业(自己手写的,高分期末作业)javascript 动态网页设计期末大作业(自己手写的,高分期末作业)javascript 动态网页设计期
混合智能体系统编队控制:分布式优化与15异构混合阶的挑战,异构混合阶智能体系统编队控制的分布式优化策略研究,15异构混合阶多智能体系统编队控制的分布式优化(无参考文献) ,核心关键词:15异构混合阶; 多智能体系统; 编队控制; 分布式优化; 无参考文献。,15混合阶多智能体系统编队分布式优化控制
javascript 动态网页设计期末大作业(自己手写的,很适合期末作业),含有代码注释,新手也可看懂,个人手打98分项目,导师非常认可的高分项目,毕业设计、期末大作业和课程设计高分必看,下载下来,简单部署,就可以使用。该项目可以直接作为毕设、期末大作业使用,代码都在里面,系统功能完善、界面美观、操作简单、功能齐全、管理便捷,具有很高的实际应用价值,项目都经过严格调试,确保可以运行! javascript 动态网页设计期末大作业(自己手写的,很适合期末作业)javascript 动态网页设计期末大作业(自己手写的,很适合期末作业)javascript 动态网页设计期末大作业(自己手写的,很适合期末作业)javascript 动态网页设计期末大作业(自己手写的,很适合期末作业)javascript 动态网页设计期末大作业(自己手写的,很适合期末作业)javascript 动态网页设计期末大作业(自己手写的,很适合期末作业)javascript 动态网页设计期末大作业(自己手写的,很适合期末作业)javascript 动态网页设计期末大作业(自己手写的,很适合期末作业)javascrip
X光安检OPIXray数据集已经转换为VOC格式,可直接转换为为YOLO
DataX--Web:图形化界面简化大数据任务管理_datax-web