2017-09-15 1 views
0

Je tente d'écrire un article scientifique sur un algorithme que j'ai développé et codé en javascript. J'espérais comparer l'ancienne version lente par rapport à la nouvelle version rapide pour diverses entrées et être capable de rapporter des métriques comme le nombre d'appels à Math.log, le nombre d'appels à Math.exp, le nombre d'opérations de multiplication, nombre d'opérations de division, le nombre d'additions, le nombre de soustractions, etc.Comptage du nombre d'opérations en virgule flottante en javascript

Je me rends compte que le compilateur JIT du moteur javascript pourrait faire une certaine optimisation qui change un peu ces chiffres, mais je ne me soucie pas vraiment de l'exact détails de chaque mesure, mais seulement que je compare des pommes aux pommes à travers les deux algorithmes.

Existe-t-il un outil ou une méthode pour comptabiliser automatiquement ces opérations en javascript? Existe-t-il des moteurs javascript qui génèrent un type de bytecode intermédiaire permettant de comptabiliser automatiquement ces opérations? Si ce n'est pas javascript, qu'en est-il en C++?

+0

Chrome peut afficher le nombre d'appels à 'Math.x' dans leurs résultats de profil. –

+0

Javascript vous permet de redéfinir les méthodes intégrées. par exemple -> 'var oLog = Math.log; Math.log = (x) => {console.log ('log'); return oLog (x); } 'sortirait de la console' log' et retournerait le journal d'origine. Donc, si vous n'avez pas trop de fonctions que vous voulez profiler, cette méthode simple pourrait faire l'affaire. – Keith

Répondre

1

Voici un exemple très simple d'envelopper le Math.log & Math.log d'origine, et de comptabiliser les appels.

Cela fonctionne parce que Javascript vous avez même le pouvoir de remplacer son intégré ..

let counts = {}; 
 

 
function profileProc(root, name, proc) { 
 
    let oProc = proc; 
 
    root[name] = function() { 
 
    counts[name] = counts[name] ? counts[name] + 1 : 1; 
 
    return oProc.apply(proc, arguments); 
 
    } 
 
} 
 

 
profileProc(Math, 'log', Math.log); 
 
profileProc(Math, 'sin', Math.sin); 
 

 
console.log(Math.log(10)); 
 
console.log(Math.sin(10)); 
 
console.log(Math.sin(20)); 
 

 
console.log(counts);

+0

Merci, je vais certainement l'utiliser pour les fonctions Math.x. Je suis plus inquiet au sujet de l'opération de base */+ - cependant. Des idées pour ceux-ci? – bruceceng

0

Eh bien, il semble que je trouve quelque chose qui fonctionne. Dans le cadre de paper.js, il y a un langage de script appelé PaperScript qui parse code écrit dans une syntaxe Javascript et ajoute la surcharge des opérateurs comme expliqué here. Fondamentalement paper.js fournit la fonction paper.PaperScript.compile(code) prend code javascript et remplace chaque opération mathématique avec un appel à

function __$__(left, operator, right) {...} 

donc une expression comme var var c = a * b; devient var c = __$__(a, '*', b); Une fois que cette transformation est faite, il est simple de modifier la fonction __$__ dans pour compter les opérations:

window.operatorCounts = {}; 
window.operatorCounts['+'] = 0; 
window.operatorCounts['-'] = 0; 
window.operatorCounts['*'] = 0; 
window.operatorCounts['/'] = 0; 
window.operatorCounts['%'] = 0; 
window.operatorCounts['=='] = 0; 
window.operatorCounts['!='] = 0; 

function __$__(left, operator, right) { 
    window.operatorCounts[operator]++; 
    switch (operator) { 
    case '+': return left + right; 
    case '-': return left - right; 
    case '*': return left * right; 
    case '/': return left/right; 
    case '%': return left % right; 
    case '==': return left == right; 
    case '!=': return left != right; 
    default: 
    throw new Error('Implement Operator: ' + operator); 
    } 
}; 

Après cette version instrumentée des opérateurs est défini, il est une question simple à exécuter la nouvelle fonction compilée. En combinant cela avec la réponse de Keith pour les fonctions Math.x, j'ai été capable d'accomplir ce que je voulais faire.