module speedTestfunction TestFunc()f=0.for i=1:10000f += Float64(i*fld(3,2))*sqrt(rand()+1.)endendfunction TestLoop()tic()for i=1:100000TestFunc()endtoc()endend
#include <julia.h>#include <iostream>#include <sys/time.h>using namespace std;typedef unsigned long long timestamp_t;static timestamp_t get_timestamp (){struct timeval now;gettimeofday (&now, NULL);return now.tv_usec + (timestamp_t)now.tv_sec * 1000000;}int main(int argc, char *argv[]){jl_init(NULL);jl_load("speedTest.jl");jl_value_t * mod = (jl_value_t*)jl_eval_string("speedTest");jl_function_t * func = jl_get_function((jl_module_t*)mod,"TestFunc");timestamp_t t0 = get_timestamp();for(int i=1; i<100000; i++) {jl_call0(func);}timestamp_t t1 = get_timestamp();double secs = (t1 - t0) / 1000000.0L;cout<< secs << endl;jl_atexit_hook(0);return 0;}
There's also the issue that we can and do turn Julia functions into C-callable function pointers that can be invoked from C as if they were C function pointers – this currently has zero overhead and if the Julia function is fast, then calling it from C will also be fast. If these require interpreter state, then that would need to be a function call argument to every C-callable function, which is at odds with many C APIs (although good libraries do allow for a void* data argument). Maybe this could be made to work, but my suspicion is that it would introduce too much overhead and destroy our current ability to do zero-cost two-way interop with C.
Except that in your example code, you aren't calling the Julia code through a raw C function pointer. You are calling it through jl_call0, which *does* have a fair amount of overhead (which you aren't seeing because the function execution is expensive enough to hide the call overhead).