Araq's Musings
Goto based exceptions

2020-01-08 des news qui montre l'activité ainsi que ce langage est vivant. (c'est une traduction mais je la trouve correct bon je pratique NIm-Lang )

La version de développement de Nim propose désormais une nouvelle implémentation de gestion des exceptions appelée "goto based exceptions". Il peut être activé via le nouveau commutateur de ligne de commande --exceptions:goto. Ce mode est également activé par --gc:arc pour la cible C.

Ce mode implémente les exceptions de manière déterministe: déclencher une exception est implémenté en définissant un indicateur d'erreur threadlocal interne qui est interrogé après chaque appel de fonction pouvant être déclenché. Ni le mécanisme setjmp de C n'est utilisé ni les tables de gestion des exceptions de C ++. Le chemin d'erreur est lié au chemin de réussite avec les avantages et les inconvénients du cache d'instructions qui en résultent. La gestion des exceptions est rapide et déterministe, il y a peu de raisons de l'éviter.

Pour améliorer la précision des capacités du compilateur à raisonner sur l'appel ,"can raise", faire un usage judicieux du .raises: [] annotation.

In http://www.filpizlo.com/papers/baker...9-accurate.pdf J. Baker, et al affirment qu'en Java, les exceptions sont levées plus fréquemment que dans le code C ++ et que cette approche l'emporte même sur l'exception typique du C ++ implémentation qui est basée sur des tables et fortement optimisée pour le cas "will not throw" .

In http://www.open-std.org/jtc1/sc22/wg...18/p0709r1.pdf Herb Sutter soutient qu'au lieu du stockage local des threads, l'indicateur d'erreur lui-même peut être conservé dans un indicateur de processeur accélérant ces branches conditionnelles et produisant un code machine plus court. Nim pourrait le faire si seuls les compilateurs C exposaient le bon ensemble d'intrinsèques. J'espère que nous verrons des correctifs pour les compilateurs C communs afin qu'ils exposent l'indicateur de portage de x86; l'assembleur en ligne ne fonctionne pas bien car il détruit efficacement la capacité de l'optimiseur à raisonner sur le code.

En d'autres termes, des moyens encore plus rapides d'implémenter des exceptions "goto based" sont connus et susceptibles de se matérialiser.

Code machine produit

With --opt:size mon GCC version 8.1 produit 2 instructions après un appel qui peuvent déclencher:
Code asm : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
cmp DWORD PTR [rbx], 0
je  .L1

Il s'agit d'une récupération de mémoire suivie d'un saut. Une implémentation idéale utiliserait l'indicateur de retenue et une seule instruction comme jc .L1 .


Référence

Cependant, pour voir que l'implémentation actuelle est déjà assez rapide, jetons un œil à ce benchmark. C'est le bon vieux fibonacci récursif qui insiste sur la surcharge de l'appel de fonction, mais j'ai également ajouté une gestion des chaînes afin que l'allocation et les destructeurs soient impliqués produisant une instruction try..finally implicite (la mémoire des chaînes produites doit être désallouée):

Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import strutils

proc fib(m: string): int =
  let n = parseInt(m)
  if n < 0:
    raise newException(ValueError, "out of range")
  elif n <= 1:
    1
  else:
    fib($(n-1)) + fib($(n-2))

import std / [times, monotimes, stats]

when defined(cpp):
  echo "C++"
elif compileOption("exceptions", "setjmp"):
  echo "setjmp"
elif compileOption("exceptions", "goto"):
  echo "goto"

var r: RunningStat
for iterations in 1..5:
  let start = getMonoTime()
  
  for i in 0 ..< 1000:
    discard fib("24") # 1 1 2 3 5 8 13
  
  r.push float((getMonoTime() - start).inMilliseconds)

echo r
J'ai compilé le programme en 3 variantes:

  1. nim cpp --gc:arc -d:danger fib.nim
  2. nim c --gc:arc --exceptions:goto -d:danger fib.nim
  3. nim c --gc:arc --exceptions:setjmp -d:danger fib.nim


On my machine I got these results:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
C++
RunningStat(
  number of probes: 5
  max: 6696.0
  min: **6416.0**
  sum: 32605.0
  mean: 6521.0
  std deviation: 102.7151400719486
)

goto
RunningStat(
  number of probes: 5
  max: 6550.0
  min: **6448.0**
  sum: 32463.0
  mean: 6492.6
  std deviation: 36.34611396009203
)

setjmp
RunningStat(
  number of probes: 5
  max: 8484.0
  min: **8331.0**
  sum: 41911.0
  mean: 8382.200000000001
  std deviation: 52.82575129612451
)
En regardant seulement le minimum, nous voyons 6416ms pour les tables d'exceptions de C ++ , 6448ms pour la gestion des exceptions basée sur goto et 8331ms pour l'ancienne gestion des exceptions basée sur setjmp.

Donc en d'autres termes, au moins pour ce benchmark particulier, la nouvelle implémentation d'exception est comparable à la gestion des exceptions basée sur les tables de C ++ tout en offrant les avantages déjà mentionnés.

Mises en garde
Dans le mode "goto based exceptions", les erreurs d'exécution vérifiées comme "Index out of bounds" ou les débordements d'entiers ne sont pas capturables et mettent fin au processus. Ceci est conforme à la spécification Nim, citant le manuel

Le fait qu'une erreur d'exécution vérifiée entraîne une exception ou une erreur fatale est spécifique à l'implémentation.

Mais je considère aussi cela comme une force: cela signifie qu'il y a une séparation plus nette entre les bogues et les erreurs d'exécution et du code comme let x = try: f() except: defaultValue ne détecte plus accidentellement les bogues de programmation.


Conclusion
La nouvelle implémentation est efficace et portable et déjà la valeur par défaut lors de la compilation via --gc: arc . Ce que j'aime le plus, c'est que le chemin de gestion des erreurs n'est pas lent non plus, cela aide les développeurs de bibliothèques: il n'y a aucune raison de diviser l'API en opérations tryParseInt et parseInt car "les exceptions devraient être des événements rares", qu'ils soient rares ou non peut dépendre de vos données d'entrée.

Generated: 2020-01-08 15:05:39 UTC


Article: https://nim-lang.org/araq/gotobased_exceptions.html

j'espère que cela vous plaira et vous incitera à allez plus loin , ce langage est très prometteur et déjà fonctionnel. des entreprises on déjà misé dessus. la programmation ce trouve simplifié, sans sacrifié la sécurité, et pour le programmeur une compilation avec ref croisée ...