Maison  >  Article  >  Java  >  Comment le code source de Spring Boot implémente StopWatch pour compter élégamment la consommation de temps

Comment le code source de Spring Boot implémente StopWatch pour compter élégamment la consommation de temps

王林
王林avant
2023-05-11 14:13:131099parcourir

Introduction

Hier, un golfeur m'a demandé si je pouvais lui expliquer ce que signifie l'annotation @SpringBootApplication et comment fonctionne Spring Boot, alors je l'y ai emmené après avoir regardé le code source de. cette annotation et la méthode run() de la classe SpringApplication, il l'a immédiatement compris.

Ne me dites pas, le processus de recherche du code source est vraiment intéressant Non, j'ai découvert un point intéressant.

public ConfigurableApplicationContext run(String... args) {
	StopWatch stopWatch = new StopWatch();
	stopWatch.start();
	......
	stopWatch.stop();
}

Spring Boot utilise StopWatch pour compter la consommation de temps, et généralement, nous utilisons System.currentTimeMillis() pour compter la consommation de temps, n'est-ce pas ? Programmation Meow ???? Il existe un tel morceau de code dans le projet open source, lorsqu'il s'agit des aspects de traitement unifié des journaux.

@Around("webLog()")
public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
    long startTime = System.currentTimeMillis();
    long endTime = System.currentTimeMillis();
    webLog.setSpendTime((int) (endTime - startTime));
}

En comparaison, nous pouvons constater que System.currentTimeMillis() fourni par JDK n'est pas aussi concis et clair que StopWatch fourni par Spring.

Utilisation de StopWatch

Surtout dans le cas du multitâche, StopWatch est si simple à utiliser ????!

// 创建一个 StopWatch 实例
StopWatch sw = new StopWatch("沉默王二是傻 X");
// 开始计时
sw.start("任务1");
Thread.sleep(1000);
// 停止计时
sw.stop();
System.out.printf("任务1耗时:%d%s.\n", sw.getLastTaskTimeMillis(), "ms");
sw.start("任务2");
Thread.sleep(1100);
sw.stop();
System.out.printf("任务2耗时:%d%s.\n", sw.getLastTaskTimeMillis(), "ms");
System.out.printf("任务数量:%s,总耗时:%ss.\n", sw.getTaskCount(), sw.getTotalTimeSeconds());

Tu vois, c'est très simple ?

  • Créez d'abord un nouvel objet StopWatch

  • puis commencez à chronométrer

    #🎜🎜 ## 🎜🎜#
  • Ensuite, arrêtez le chronomètre
  • Enfin obtenez le décalage horaire via sw.getLastTaskTimeMillis()
  • #🎜 🎜## 🎜🎜#Si vous passez à System.currentTimeMillis(), vous mourrez. Vous devez d'abord déclarer plusieurs variables locales de type long, puis soustraire la première de la seconde, et soustraire la seconde de la troisième. un. Soyez un peu négligent (surtout lorsque vous utilisez la méthode CV, il est facile de faire des erreurs.

  • En plus de l'heure locale, vous pouvez également obtenir la durée totale via sw.getTotalTimeSeconds().

La tâche 1 a pris 1002 ms

De plus, StopWatch fournit également une méthode sw.prettyPrint() pour imprimer des résultats magnifiquement formatés :
# 🎜🎜#

StopWatch 'Le Roi Silencieux est stupide' : durée d'exécution = 2108529351 ns
------------------------- -------------------- ------
ns       %   Nom de la tâche

------------ -------------------- -------------
1004338467 048% Tâche 1

1104190884 052% Tâche 2

Il y a une consommation de temps et un pourcentage d'occupation, et le nom de la tâche est très clair.

En plus de Spring, la bibliothèque d'outils hutool et le package d'outils communs Apache fournissent leur propre StopWatch.


En regardant le code source de StopWatch dans la bibliothèque d'outils hutool, nous pouvons voir que cette classe provient en fait de StopWatch.java de Spring, et son utilisation est exactement pareil.

Cela montre que l'auteur de hutool pense aussi que Spring's StopWatch est bien écrit, hahaha ????. Comment le code source de Spring Boot implémente StopWatch pour compter élégamment la consommation de temps

Utilisez Beyond compare pour comparer

Après avoir comparé avec Beyond compare, nous pouvons également constater qu'à l'exception d'un commentaire chinois et d'un commentaire anglais, les codes sont presque les mêmes. La méthode setKeepTaskList est assez différente.

Comment le code source de Spring Boot implémente StopWatch pour compter élégamment la consommation de temps

C'est-à-dire que si vous n'utilisez pas Spring Family Bucket dans votre projet et utilisez uniquement la boîte à outils hutool, vous pouvez utiliser le StopWatch de hutool pour remplacer System .currentTimeMillis().

En analysant le code source de la méthode stop de StopWatch :

public void stop() throws IllegalStateException {
	if (null == this.currentTaskName) {
		throw new IllegalStateException("Can't stop StopWatch: it's not running");
	}
	final long lastTime = System.nanoTime() - this.startTimeNanos;
	this.totalTimeNanos += lastTime;
	this.lastTaskInfo = new TaskInfo(this.currentTaskName, lastTime);
	if (null != this.taskList) {
		this.taskList.add(this.lastTaskInfo);
	}
	++this.taskCount;
	this.currentTaskName = null;
}

En fait, on peut constater que StopWatch est chronométré en interne via System.nanoTime(), qui est essentiellement le identique à System.currentTimeMillis( ) La différence n'est pas énorme.

Comment le code source de Spring Boot implémente StopWatch pour compter élégamment la consommation de tempsnanoTime est plus granulaire que currentTimeMillis. Le premier est en nanosecondes et le second en millisecondes.

Notez que les deux sont des méthodes natives, c'est-à-dire que la granularité de la valeur dépend en réalité du système d'exploitation sous-jacent.

Après avoir vu cela, vous réaliserez peut-être soudainement que StopWatch n'est que System.currentTimeMillis() dans un manteau ?

Mais ce qui est merveilleux c'est que ce manteau est assez beau et assez élégant. StopWatch peut enregistrer le nom de chaque sous-tâche et imprimer les résultats dans un format plus convivial, en particulier pour les statistiques multitâches.

Comment le code source de Spring Boot implémente StopWatch pour compter élégamment la consommation de tempsBien sûr, en plus de choisir StopWatch de Spring et hutool, StopWatch d'Apache commons-lang3 est également une bonne option, qui est plus flexible et modifiable.

StopWatch sw = StopWatch.createStarted();
Thread.sleep(1000);
System.out.printf("耗时:%dms.\n", sw.getTime());

Les deux autres objets StopWatch créés via new, commons-lang3 peuvent également être complétés via createStarted (créer et démarrer immédiatement), create (créer).

Vous pouvez également appeler la méthode suspend pour suspendre le chronométrage, la méthode de reprise pour reprendre le chronométrage et la méthode de réinitialisation pour redémarrer le chronométrage.

// 暂停计时
sw.suspend();
System.out.printf("暂停耗时:%dms.\n", sw.getTime());
// 恢复计时
sw.resume();
System.out.printf("恢复耗时:%dms.\n", sw.getTime());
// 停止计时
sw.stop();
System.out.printf("总耗时:%dms.\n", sw.getTime());
// 重置计时
sw.reset();
// 开始计时
sw.start();
System.out.printf("重置耗时:%dms.\n", sw.getTime());

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer