skip to Main Content

What is the difference between using '%OptimizeFunctionOnNextCall()' alone and using '%OptimizeFunctionOnNextCall()' accompanied with '%PrepareFunctionForOptimization()‘?

function test() {
    // some code here to optimize
}

%OptimizeFunctionOnNextCall(test);
test();

// ./d8 test.js --allow-natives-syntax --trace-turbo --trace-turbo-path turbo_out --trace-turbo-filter test
function test() {
    // some code here to optimize
}

%PrepareFunctionForOptimization(test);
test();
%OptimizeFunctionOnNextCall(test);
test();

// ./d8 test.js --allow-natives-syntax --trace-turbo --trace-turbo-path turbo_out --trace-turbo-filter test

2

Answers


  1. function test() {
        // some code here to optimize
    }
    %OptimizeFunctionOnNextCall(test);
    test();  // This call will trigger the optimization of the test function
    

    This approach works well if the function is already in a state that can be optimized (e.g., it has been called enough times to gather type feedback).

    function test() {
        // some code here to optimize
    }
    %PrepareFunctionForOptimization(test);
    test();  // This call prepares the function and gathers feedback
    %OptimizeFunctionOnNextCall(test);
    test();  // This call will trigger the optimization of the test function
    

    This approach is more robust, especially if the function might have been deoptimized or hasn’t gathered enough type feedback yet. %PrepareFunctionForOptimization ensures that the function is in a clean state, ready to be optimized on the next call.

    Login or Signup to reply.
  2. V8 parses and compiles functions lazily (even the compilation to unoptimized bytecode is lazy), and allocates feedback lazily.

    Lazy bytecode compilation is not very relevant to this question and to PrepareFunctionForOptimization/OptimizeFunctionOnNextCall (well, PrepareFunctionForOptimization forces the function to be compiled to bytecode if it’s not already compiled, but I don’t think that this makes a different for OptimizeFunctionOnNextCall).

    However, lazy feedback vector allocation is relevant. For Turbofan/Maglev compilation to have any benefit, a function needs to have ran a few times and collected feedback on what its inputs are. %PrepareFunctionForOptimization ensures that the function has a feedback vector allocated (cf its implementation).

    So, the normal flow to write JavaScript unit tests for V8 is thus typically

    %PrepareFunctionForOptimization(foo); // Allocates feedback vector
    foo(); // Collect feedback
    %OptimizeFunctioOnNextCall(foo); // Trigger optimization on next call, which will
    foo();                           // optimize based on the feedback collected so far. 
    

    Note that using %OptimizeFunctionOnNextCall without having called %PrepareFunctionForOptimization before should crash (unless you use specific flags like --fuzzing), because it’s pretty much never what you want: optimizing without feedback is very rarely useful.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search