The performance of my scripting language is not good

Hi all,

So, for the past couple of months (not full time, though) I have been learning Rust and trying to develop a set of programs. One of them is a scripting language that (for now, at least) is called ppl. This is supposed to work as an entry point my other applications (this might be useful for other of you...?). It is in very early stages, but it has been a great learning process for me.

Anyway, so I have not optimized my code for performance at all yet, but I ran a simple benchmark and I noticed that Lua and Ruby are both quite faster than ppl.

/* This code takes about :
ppl: 60 seconds 
Ruby: 14 seconds
Lua: 27 seconds
*/
fn fib(n){    
    if n < 2 {
        return n
    }else{
        return fib(n - 1) + fib(n - 2)
    }
}

let y = fib(40)

io::print(y)
io::print(y == 102334155)
/* This code takes about :
ppl: 14 seconds 
Ruby: 1.8 seconds
Lua: 9 seconds
*/

let a = 1

while a < 99999999 {    
    a = a + 1
}

I did some profiling, and it seems to be that this function is taking most of the workload. This surprised me as this function is, essentially, a match statement (the functions called from it were not as critical... am I profiling correctly?). So, I wonder if this has to do with the size of my operations (which are not bytes, but enum variants with content), but I did some reductions in size, but the performance was not improved.

So, I am now wondering what am I doing for this to be so slow. Is this a programming thing? or a programming-language-design thing?

Any respectful feedback is welcome!

your links are broken, is your repository set to private?

Links are broken – is the repository private?


Without seeing the code, I have two things to say, though:

  • Are you running your interpreter in release mode (cargo run --release)?
  • Modern scripting languages made specific design decisions in their interpreter code in order to achieve good performance. They are usually register-based virtual machines, compiled to byte code, use specialized (very fast) hash table implementations for fast lookup of object members, etc. You are probably not going to be able to outperform them in a couple-months-long project.

Incidentally, I have made a toy scripting language before, which uses a stack machine and a not-very-naïve bytecode interpreter. I was able to get within an order of magnitude of the performance of Lua in the average median case, and I could sometimes outperform Python. (The latter was not typical at all, though, if I recall correctly – although it's been a long time since I've done the benchmarks.)

I did, however, run out of ideas regarding performance improvement eventually, and to this day, I'm not entirely sure where Lua gets its 2…5x performance improvement over my code. The code of the Lua compiler and interpreter is kind of hard to read – it is full of subtle inconsistencies, and the developers' naming convention is not exactly mainstream, making the comments less helpful than they could have been.

1 Like

Idiot me. It is now public!

Thanks for your answer! I think it really helps me to understand that it might be the implementation and not a 'you are cloning too much' thing.

I did not really expect to beat these two languages but the difference in performance made me think I was missing something. In fact, since the idea is to use my language to run Rust code, I do not think performance is the most crucial point at this point.

I've played around with "virtual machines" a bit and I can say that it's okay to have slow, stack-based machines, which is why jvm uses jit. The Lua machine is based on register which is why it is so fast. But what is really fast are the various extensions that C has. A notable example of such an extension is Label as Value.
Read the page to understand better.
https://gcc.gnu.org/onlinedocs/gcc-4.1.2/gcc/Labels-as-Values.html

Thanks a lot. I will have a look at these things: The extensions and the register-based VMs.

I will keep coding as I am doing it now, then!

1 Like