Is this a valid way of evaluating string of code in local scope?

From what I’ve read and observed, it seems like there isn’t a way of eval-ing code in local scope or otherwise without incurring significant performance penalty (lots of extra memory allocations and significantly longer run time). However, this seems like a solution for our particular use-case.

# Top-level scope here
for _ in 1:1
    data = Dict()
    while receive_request_from_aws_sqs())
        code = get_code_from_sqs()
        include_string(Main, code) # code defines a function exec_code
        function exec()
            for iter in 1:4
                @time begin
                    exec_code(data)
                end
            end
        end
        exec()
    end
end

Is this reasonable? Is there some part of this that looks unnecessary?

We’re using @time because @btime executes in global state so we can’t evaluate how much time it takes to operate multiple instances of code coming in from SQS. So, we’re using @time in a function based on our recommendation of Performance Tips · The Julia Language. Is that the best way of doing this.

Any input would be greatly appreciated.

No, that is not feasible. But you can write a function that returns a function. Which is probably what you want to do.

Hi @pdeffebach,

Thanks for your reply but we really do need to evaluate arbitrary code that can share state stored in a dictionary. We have a serverless function that generates cache-optimized Julia code.

Also, if I may ask, why exactly is this infeasible? Where would I run in to issues performance or otherwise? Isn’t everything here in local scope since the whole thing is wrapped in a for (should it be let?) and include_string is generating a function with locally scoped variables and this function is then being called from exec? Where would we run into issues with this?

I don’t have the expertise to explain exactly why this is infeasible. But it has to do with world age issues from modifying the global state method table inside a local scope. Hopefully someone more informed than I an can explain it more clearly.

Well, it is working in this case. But I’m not entirely sure why.

In the code, I note that the for loop is in top-level scope. So the include_string is able to create a function that can then be subsequently called. But the dictionary passed in is presumably in some sort of local scope. Or perhaps I am mistaken about that and maybe the dictionary is actually a global variable. Is there any disadvantage of that?

The Dict will store arbitrary values anyway (it’s effectively a Dict{Symbol, Any} so Julia wouldn’t be able to optimize usage of it necessarily. The function exec_code does create local variables produced by calling functions on Dict entries. Could this lead to a slowdown (for now, I’m just generating code that operates on data created in local variables but in the future I may be getting that data from the data dictionary)?

Aside from the details about scope and how include works, if you can write a function which spits out valid Julia code, you can also write a function that returns a closure, right? Surely the second option must be easier.

1 Like