Introduction to Lua
In this chapter, we briefly introduce the basics of Lua, and in particular, we intend to place the discussion in the context of OpenResty. At the same time, we won’t shy away from LuaJIT’s unique new features; of course, when we encounter such unique features, we will explain them. We will look at the potential impact of language structures and standard library functions on performance. When discussing performance-related issues, we only care about LuaJIT implementations.
What is Lua?
In 1993, a programming language was born at Pontifical Catholic University of Rio de Janeiro in Brazil by three researchers who gave the language a romantic name, Lua, representing the beautiful moon in Portuguese. It turned out that she had not spoiled this beautiful word, and Lua grew into a simple, elegant and fun language as its name predicted.
Lua has been designed as a lightweight scripting language for easy embedding (other applications) and extensibility since its inception. Therefore, Lua has always followed the principles of simplicity, compactness, portability, and rapidity. The official implementation is written entirely in ANSI C and can be embedded into the host program in the form of a C library. LuaJIT 2 and standard Lua 5.1 interpreter adopt the famous MIT license agreement. Because of the above characteristics, Lua has been widely used in game development, robot control, distributed applications, image processing, bioinformatics, and other fields. Among them, game development is the most important. Many famous games, such as Escape from Monkey Island, World of Warcraft and Big Talk Westward Travel, adopt Lua to cooperate with the engine to complete data description, configuration management, and logical control tasks. Even a neutral memory key database like Redis provides official support for embedded user Lua scripts.
As a procedural dynamic language, Lua has the following characteristics:
- The variable name has no type, the value has a type, and the variable name can be bound to any type of value at run time.
- The language provides only one data structure, called table, which mixes arrays, hashes, and can use any type of value as key and value. It provides a consistent and expressive table construction grammar, which makes Lua suitable for describing complex data.
- Functions are of the first class, supporting anonymous functions and proper tail recursion.
- Lexical scoping and closure;
- It provides the threaded type and structured coroutine mechanism, on which collaborative multi-task can be easily realized.
- The runtime can compile the program text in the form of strings and load it into the virtual machine for execution.
- The dynamic meta-mechanism is provided by metatable and metamethod, which allows the program to change or expand the internal meaning of the grammar facilities according to its needs.
- The dynamic meta-mechanism is provided by metatable and metamethod, which allows the program to change or expand the internal meaning of the grammar facilities according to its needs.
- It can easily implement a prototype-based object-oriented model by using table and dynamic meta-mechanism.
- Since version 5.1, it has provided a perfect module mechanism to better support the development of large-scale applications.
Lua’s grammar is similar to that of Pascal and Modula, but more concise. All the EBNF rules are just over 60. Programmers who are familiar with C and Pascal usually need only half an hour to master them completely. Semantically, Lua is very similar to Scheme. They fully share the above 1, 3, 4 and 6 features. The continuation and cooperation of Scheme are basically the same, but the degree of freedom is higher. Most notably, both languages provide only one data structure: Lua’s table and Schemes’list. Because of this, some people even call Lua “Scheme for Tables Only”.
The difference between Lua and LuaJIT
Lua is very efficient and runs faster than many other scripts (such as Perl, Python, Ruby), which has been confirmed in independent third-party evaluations. Nevertheless, there will still be some people who are not satisfied, they always feel “well, not fast enough!” LuaJIT is an attempt to squeeze out some more speed. It uses Just-in-Time technology to compile Lua code and send it to the CPU to execute directly. The evaluation report of LuaJIT 2 shows that its acceleration effect is remarkable in many aspects, such as numerical operation, loop and function call, coprocess switching, string operation and so on. With FFI features, LuaJIT 2 is much faster than the standard Lua interpreter in scenarios where external C/C++ code needs to be frequently invoked. At present, LuaJIT 2 has supported many different architectures, including i386, x86_64, ARM, PowerPC, and MIPS.
LuaJIT is a Lua interpreter and instant compiler written in C and assembly language. LuaJIT is designed to be fully compatible with the standard Lua 5.1 language, while optionally supporting some useful features of Lua 5.2 and Lua 5.3 that do not undermine backward compatibility. Therefore, the code of the standard Lua language can run on LuaJIT without modification. A big difference between LuaJIT and standard Lua interpreter is that the execution speed of LuaJIT, even it’s assembled Lua interpreter, is much faster than the standard Lua 5.1 interpreter, which can be said to be an efficient Lua implementation. Another difference is that LuaJIT supports more basic terms and features than the standard Lua 5.1 language, so it’s also more powerful.