extism / cpp-sdk

Extism C++ Host SDK
BSD 3-Clause "New" or "Revised" License
7 stars 3 forks source link

Passing large input affects performance forever #15

Closed G4Vi closed 6 months ago

G4Vi commented 7 months ago

I have a plugin built with the c-pdk, that has one function that does nothing:

int32_t EXTISM_EXPORTED_FUNCTION(decoder_extism_nop)
{
  return 0;
}

and a host program using the cpp-sdk:

static void bench_extism_call(extism::Plugin &plugin)
{
    while (1)
    {
        const auto start{std::chrono::steady_clock::now()};
        plugin.call("decoder_extism_nop");
        const auto end{std::chrono::steady_clock::now()};
        const std::chrono::duration<double> elapsed_seconds{end - start};
        std::cerr << "took " << elapsed_seconds.count() << " seconds to do an extism call." << std::endl;
        return;
    }
}

int main(int argc, char *argv[])
{
    extism::Manifest manifest = extism::Manifest::wasmPath("wasm-src/plugin.wasm");
    extism::Plugin plugin(manifest, true);
    const uint32_t fifty_mebib = 50 * 1024 * 1024;
    void *temp = malloc(fifty_mebib);
    bench_extism_call(plugin);
    bench_extism_call(plugin);
    plugin.call("decoder_extism_nop", (const uint8_t *)temp, fifty_mebib);
    free(temp);
    bench_extism_call(plugin);
    bench_extism_call(plugin);
    bench_extism_call(plugin);
    bench_extism_call(plugin);
    bench_extism_call(plugin);
    bench_extism_call(plugin);
    bench_extism_call(plugin);
    bench_extism_call(plugin);
    bench_extism_call(plugin);
    return 0;

As you can see bench_extism_call and main both call the same plugin function, decoder_extism_nop . bench_extism_call doesn't pass any input data to the plugin function. Before passing the large input, decoder_extism_nop is pretty fast:

took 0.000332847 seconds to do an extism call.
took 5.4292e-05 seconds to do an extism call.

after passing the large input, it takes tens of milliseconds:

took 0.0194691 seconds to do an extism call.
took 0.0219667 seconds to do an extism call.
took 0.0236935 seconds to do an extism call.
took 0.0153126 seconds to do an extism call.
took 0.0107325 seconds to do an extism call.
took 0.00980626 seconds to do an extism call.
took 0.0104758 seconds to do an extism call.
took 0.0098605 seconds to do an extism call.
took 0.00947281 seconds to do an extism call.
zshipko commented 7 months ago

I believe I have a fix here: https://github.com/extism/extism/pull/627 just need to do a little more testing tomorrow.

G4Vi commented 7 months ago

The fix is a huge improvement! It fixes all "too slow" calls in my miniaudio integration except for the first call. I'm able to fix that by inserting a call a decoder_extism_nop after my call that passes a lot of input.

I'll look closer at this tomorrow.

zshipko commented 7 months ago

Awesome! One thing I was considering was adding a extism_plugin_reset function to the SDK so users can control when that reset happens. It could be used instead of the call to decoder_extism_nop but that's only necessary if I can't find any additional improvements.

chrisdickinson commented 6 months ago

Fixed in https://github.com/extism/extism/pull/627 (for posterity!)