Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!


Shells Virtual Desktop
BMail.ag - Secure Email Service
Server.net
CPLicense.net
VPS Server
Buy VPN
Vultr
VMs for AI
HostDare
HostDare
ReliableSite White-Label Dedicated Hosting for Resellers
InterServer VPS
BMail.ag - Secure Email Service
Best VPN
High-Performance Bare Metal Server Solutions
Karvl.com
Server Mania Cloud Hosting
DataWagon Hosting
AlphaVPS Hosting
Evoxt.com
Clouvider
VPS Hosting with NVMe
Residential IPs in the US & 4G Mobile Proxies in EU & US with Unlimited Bandwidth
ReliableSite White-Label Dedicated Hosting for Resellers
Rabisu - Hosting Solutions
Shells Virtual Desktop
New on LowEndTalk? Please Register and read our Community Rules.

All new Registrations are manually reviewed and approved, so a short delay after registration may occur before your account becomes active.

Apt, Apache, and Lua

Not_OlesNot_Oles Member, Patron Provider

Today I tried upgrading my server which is running Debian unstable. I noticed that apache2 was held back. Here are some notes and a few questions at the end. Any help and comments will be greatly appreciated. Thanks!

Apt and Apache

root@lol ~ # apt-get update
Get:1 http://deb.debian.org/debian unstable InRelease [198 kB]
Get:2 http://deb.debian.org/debian unstable/main Sources [10.6 MB]
Get:3 http://deb.debian.org/debian unstable/main amd64 Packages [9,944 kB]
Get:4 http://deb.debian.org/debian unstable/main Translation-en [7,230 kB]
Fetched 28.0 MB in 2s (16.2 MB/s)                               
Reading package lists... Done
root@lol ~ # apt-get upgrade
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
Calculating upgrade... Done
The following packages have been kept back:
  apache2 apache2-bin apache2-data apache2-utils
0 upgraded, 0 newly installed, 0 to remove and 4 not upgraded.
root@lol ~ #

I wondered why apache2 was held back. I took a quick look at man apt-get and then tried to investigate with the --dry-run flag.

root@lol ~ # man apt-get
root@lol ~ # apt-get full-upgrade --dry-run
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
Calculating upgrade... Done
The following package was automatically installed and is no longer required:
  liblua5.3-0
Use 'apt autoremove' to remove it.
The following NEW packages will be installed:
  liblua5.4-0
The following packages will be upgraded:
  apache2 apache2-bin apache2-data apache2-utils
4 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Inst liblua5.4-0 (5.4.6-3+b1 Debian:unstable [amd64])
Inst apache2 [2.4.59-2] (2.4.60-1 Debian:unstable [amd64]) []
Inst apache2-bin [2.4.59-2] (2.4.60-1 Debian:unstable [amd64]) []
Inst apache2-data [2.4.59-2] (2.4.60-1 Debian:unstable [all]) []
Inst apache2-utils [2.4.59-2] (2.4.60-1 Debian:unstable [amd64])
Conf liblua5.4-0 (5.4.6-3+b1 Debian:unstable [amd64])
Conf apache2 (2.4.60-1 Debian:unstable [amd64])
Conf apache2-bin (2.4.60-1 Debian:unstable [amd64])
Conf apache2-data (2.4.60-1 Debian:unstable [all])
Conf apache2-utils (2.4.60-1 Debian:unstable [amd64])
root@lol ~ # 

Lua and Apache

Looks like

  • liblua5.3.0 had been installed,
  • the apache upgrade wanted liblua5.4.0, and that
  • apt was being careful by not auto-removing liblua5.3.0, which might have been in use.

Lua? Why Lua? I didn't remember installing liblua. I had heard that Lua was a computer language, but I didn't know about Lua.

The first result of a Google search for "liblua apache" was a link to an article, Lua for Apache, at admin-magazine.com. The article didn't seem to have a date, which always is a big red flag for me, but I decided to take a quick look. I was surprised that the article seemed well written.

I noticed that the article listing on Admin-magazine's home page had dates. So I searched in their search box for articles containing the word "lua." The second result was the article I wanted, Lua for Apache. The listing contained the date "10.07.2012."

The article explains that Lua is a scripting language developed in 1993 with these prominent features:

  • small, fast interpreter,
  • C interface,
  • imperative and functional,
  • "rudimentary" support for object-oriented programming, and
  • "minimal syntax."

The article says that the minimal syntax "makes Lua programs more cryptic than their PHP counterparts."

According to the article, there have been several implementations of Lua scripting for Apache. Several implementations are listed in the article. One of these, mod_wombat, by Brian McCallister, in 2006, has become [had become by 2012?] the mod_lua in the Apache mod family along with mod_perl and mod_php.

The article continues with

  • how to compile Apache with Lua enabled,
  • Apache configuration [again from 2012?] for Lua,
  • a Lua Hello world example,
  • an example form for first and last name, and
  • a discussion of hooks.

Questions

It looks like my Apt and apt-get options include

  • apt autoremove and then apt-get upgrade, and
  • apt-get full-upgrade.

Do I understand right that the former will leave liblua marked as autoinstalled, but that the latter will mark liblua as manually installed?

Does anybody here use Lua? Does anybody here use Lua with Apache? If yes, what particular feature of Lua appeals to you for your project?

New Apt Terminal Colors

By the way, Apt in Debian unstable has cool new terminal output colors! The new Apt colors look really great! It's fun to watch the Apt output!

Wish

Speaking of terminal colors, is anybody here using Wish?

Thanked by 1ask_seek_knock
«1

Comments

  • edited July 2024

    First off apologies for mostly skimming your post but i think apt holding back the packages is because of increasing versions (a basic upgrade only pulls in patches for the version already installed and doesn't actually update packages to newer versions). Given you are running unstable version updates aren't that uncommon (it seldom happens on stable too but there it's rather the exception that the norm - i.e. packages that have to update to new versions like Firefox ESR when support runs out for example).

    The sudden addition of LUA is probably due to the newer version of Apache coming with some kind of LUA module that needs it. As for marking it as manually installed i kind of doubt any kind of upgrade would do that but then i don't really know full-upgrade. If i want to update to new versions i use dist-upgrade but i wouldn't be surprised if full-upgrade would just be a newer alias for dist-upgrade. TLDR: As long as you don't explicitly install something and it just gets pulled in by something else it should not be marked as manually installed.

    On LUA in general: It's an OK scripting language. I'm not a big fan but from my perspective it's still one of the more pleasant options.

    Thanked by 2Not_Oles lanefu
  • Not_OlesNot_Oles Member, Patron Provider

    @totally_not_banned said: First off apologies for mostly skimming your post

    No worries! There's a lot in there.

    [comments about Apt]

    Thanks for these helpful comments! I need to study up more about Apt. I already mentioned it above, but I will say it again, the colored output of the new Apt is really nice!

    [Lua]

    Nobody here uses Lua? Really?

  • entrailzentrailz Member, Host Rep
    edited July 2024

    @Not_Oles said:

    @totally_not_banned said: First off apologies for mostly skimming your post

    No worries! There's a lot in there.

    [comments about Apt]

    Thanks for these helpful comments! I need to study up more about Apt. I already mentioned it above, but I will say it again, the colored output of the new Apt is really nice!

    [Lua]

    Nobody here uses Lua? Really?

    Cloudflare use Lua pretty heavily!

    Thanked by 1Not_Oles
  • FlorinMarianFlorinMarian Member, Host Rep

    @entrailz said:

    @Not_Oles said:

    @totally_not_banned said: First off apologies for mostly skimming your post

    No worries! There's a lot in there.

    [comments about Apt]

    Thanks for these helpful comments! I need to study up more about Apt. I already mentioned it above, but I will say it again, the colored output of the new Apt is really nice!

    [Lua]

    Nobody here uses Lua? Really?

    Cloudflare use Lua pretty heavily!

    FYI..also the AntiDDoS solution that I wrote for my college thesis is also written in LUA.

  • edited July 2024

    @Not_Oles said:

    [Lua]

    Nobody here uses Lua? Really?

    Define 'using' ;)

    I've used LUA for game scripting when that was the language of choice and i prefer it over Python any day due to being procedural (there might be some OO extension but i've never noticed it) and overall conservative enough to let me get by with looking stuff up as needed. The JIT engine is also surprisingly fast. I still wouldn't claim to be using LUA.

    If TCL wasn't a thing i might be doing more LUA. It's the next best thing for integrated scripting after all but outside of that i'm not sure if i wouldn't just use PHP instead.

    Thanked by 1Not_Oles
  • Not_OlesNot_Oles Member, Patron Provider

    @entrailz said: Cloudflare use Lua pretty heavily!

    @entrailz Thanks for this! I didn't know! I found https://blog.cloudflare.com/more-consistent-luajit-performance which is a really interesting blog post from December 2018 covering Lua performance testing at King's Collge London that was sponsored by Cloudflare. The post doesn't talk about why Cloudflare uses Lua and where Cloudflare uses Lua, but it sure seems clear that Cloudflare had been looking at Lua very carefully as of 2018. Fun to read!

  • Not_OlesNot_Oles Member, Patron Provider

    @FlorinMarian said: FYI..also the AntiDDoS solution that I wrote for my college thesis is also written in LUA.

    Interesting! May I please have a link? Thanks!

  • Not_OlesNot_Oles Member, Patron Provider

    @totally_not_banned said: Define 'using'

    "Using" means it runs on at least one your servers at least every once in a while. :)

    @totally_not_banned said: If TCL wasn't a thing

    A friend kindly showed me some TCL. Amazing what TCL can do!

    @totally_not_banned said: The JIT engine is also surprisingly fast.

    The article linked in the OP, Lua for Apache, prominently mentions "small, fast interpreter." Interpreter speed also is what the Clooudflare-sponsored testing focussed upon. Florin used Lua for his DDoS protection, which would need to be fast. And now you also summarize Lua's speed as "surprisingly fast." So I now get it that the fast interpreter might be one (the?) major reason for adoption of Lua. Thanks!

    Anybody else here actually using Lua? Thanks!

    Thanked by 1totally_not_banned
  • entrailzentrailz Member, Host Rep

    @Not_Oles said:

    @entrailz said: Cloudflare use Lua pretty heavily!

    @entrailz Thanks for this! I didn't know! I found https://blog.cloudflare.com/more-consistent-luajit-performance which is a really interesting blog post from December 2018 covering Lua performance testing at King's Collge London that was sponsored by Cloudflare. The post doesn't talk about why Cloudflare uses Lua and where Cloudflare uses Lua, but it sure seems clear that Cloudflare had been looking at Lua very carefully as of 2018. Fun to read!

    Their most recent outage mentions their usage of Lua here:

    https://blog.cloudflare.com/cloudflare-incident-on-june-20-2024

    Thanked by 1Not_Oles
  • SirFoxySirFoxy Member
    edited July 2024

    Garry's Mod put a lot of kids onto Lua:

    https://garry.net/posts/lua-the-programming-language

    You could make thousands of dollars in high school running a server and selling VIP perks 💀

    Thanked by 1Not_Oles
  • Not_OlesNot_Oles Member, Patron Provider

    @Not_Oles said: It looks like my Apt and apt-get options include

    apt autoremove and then apt-get upgrade, and
    apt-get full-upgrade.

    Do I understand right that the former will leave liblua marked as autoinstalled, but that the latter will mark liblua as manually installed?

    This morning:

    root@lol ~ # date; apt autoremove
    Wed Jul  3 07:18:30 PM UTC 2024
    Summary:                        
      Upgrading: 0, Installing: 0, Removing: 0, Not Upgrading: 4
    root@lol ~ # 
    

    Looks like a couple more updates were added since yesterday.

    root@lol ~ # date; apt update
    Wed Jul  3 07:22:25 PM UTC 2024
    Get:1 http://deb.debian.org/debian unstable InRelease [198 kB]
    Get:2 http://deb.debian.org/debian unstable/main Sources [10.6 MB]
    Get:3 http://deb.debian.org/debian unstable/main amd64 Packages [9,945 kB]
    Get:4 http://deb.debian.org/debian unstable/main Translation-en [7,229 kB]
    Fetched 28.0 MB in 2s (16.3 MB/s)                               
    11 packages can be upgraded. Run 'apt list --upgradable' to see them.
    root@lol ~ # apt list --upgradeable
    apache2-bin/unstable 2.4.60-1 amd64 [upgradable from: 2.4.59-2]
    apache2-data/unstable 2.4.60-1 all [upgradable from: 2.4.59-2]
    apache2-utils/unstable 2.4.60-1 amd64 [upgradable from: 2.4.59-2]
    apache2/unstable 2.4.60-1 amd64 [upgradable from: 2.4.59-2]
    apt-utils/unstable 2.9.6 amd64 [upgradable from: 2.9.5]
    apt/unstable 2.9.6 amd64 [upgradable from: 2.9.5]
    curl/unstable 8.8.0-2 amd64 [upgradable from: 8.8.0-1]
    libapt-pkg6.0t64/unstable 2.9.6 amd64 [upgradable from: 2.9.5]
    libcurl3t64-gnutls/unstable 8.8.0-2 amd64 [upgradable from: 8.8.0-1]
    libcurl4t64/unstable 8.8.0-2 amd64 [upgradable from: 8.8.0-1]
    libnbd0/unstable 1.20.2-1 amd64 [upgradable from: 1.20.1-1+b1]
    root@lol ~ # apt full-upgrade
    The following package was automatically installed and is no longer required:
      liblua5.3-0
    Use 'apt autoremove' to remove it. 
    
    Upgrading:
      apache2       apache2-utils  curl                libcurl4t64
      apache2-bin   apt            libapt-pkg6.0t64    libnbd0
      apache2-data  apt-utils      libcurl3t64-gnutls
    
    Installing dependencies:
      liblua5.4-0  libnghttp3-9  libngtcp2-16  libngtcp2-crypto-gnutls8
    
    Summary:
      Upgrading: 11, Installing: 4, Removing: 0, Not Upgrading: 0
      Download size: 6,401 kB
      Space needed: 1,298 kB / 2,840 GB available
    
    Continue? [Y/n] 
    Get:1 http://deb.debian.org/debian unstable/main amd64 libapt-pkg6.0t64 amd64 2.9.6 [1,020 kB]
    Get:2 http://deb.debian.org/debian unstable/main amd64 apt amd64 2.9.6 [1,398 kB]
    Get:3 http://deb.debian.org/debian unstable/main amd64 apt-utils amd64 2.9.6 [328 kB]
    Get:4 http://deb.debian.org/debian unstable/main amd64 libnghttp3-9 amd64 1.3.0-2 [64.7 kB]
    Get:5 http://deb.debian.org/debian unstable/main amd64 libngtcp2-16 amd64 1.5.0-2 [126 kB]
    Get:6 http://deb.debian.org/debian unstable/main amd64 libngtcp2-crypto-gnutls8 amd64 1.5.0-2 [22.9 kB]
    Get:7 http://deb.debian.org/debian unstable/main amd64 libcurl3t64-gnutls amd64 8.8.0-2 [451 kB]
    Get:8 http://deb.debian.org/debian unstable/main amd64 curl amd64 8.8.0-2 [347 kB]
    Get:9 http://deb.debian.org/debian unstable/main amd64 libcurl4t64 amd64 8.8.0-2 [445 kB]
    Get:10 http://deb.debian.org/debian unstable/main amd64 liblua5.4-0 amd64 5.4.6-3+b1 [147 kB]
    Get:11 http://deb.debian.org/debian unstable/main amd64 apache2 amd64 2.4.60-1 [215 kB]
    Get:12 http://deb.debian.org/debian unstable/main amd64 apache2-bin amd64 2.4.60-1 [1,385 kB]
    Get:13 http://deb.debian.org/debian unstable/main amd64 apache2-data all 2.4.60-1 [160 kB]
    Get:14 http://deb.debian.org/debian unstable/main amd64 apache2-utils amd64 2.4.60-1 [209 kB]
    Get:15 http://deb.debian.org/debian unstable/main amd64 libnbd0 amd64 1.20.2-1 [83.1 kB]
    Fetched 6,401 kB in 0s (81.7 MB/s)  
    (Reading database ... 98291 files and directories currently installed.)
    Preparing to unpack .../libapt-pkg6.0t64_2.9.6_amd64.deb ...
    Unpacking libapt-pkg6.0t64:amd64 (2.9.6) over (2.9.5) ...
    Setting up libapt-pkg6.0t64:amd64 (2.9.6) ...
    (Reading database ... 98291 files and directories currently installed.)
    Preparing to unpack .../archives/apt_2.9.6_amd64.deb ...
    Unpacking apt (2.9.6) over (2.9.5) ...
    Setting up apt (2.9.6) ...
    (Reading database ... 98291 files and directories currently installed.)
    Preparing to unpack .../00-apt-utils_2.9.6_amd64.deb ...
    Unpacking apt-utils (2.9.6) over (2.9.5) ...
    Selecting previously unselected package libnghttp3-9:amd64.
    Preparing to unpack .../01-libnghttp3-9_1.3.0-2_amd64.deb ...
    Unpacking libnghttp3-9:amd64 (1.3.0-2) ...
    Selecting previously unselected package libngtcp2-16:amd64.
    Preparing to unpack .../02-libngtcp2-16_1.5.0-2_amd64.deb ...
    Unpacking libngtcp2-16:amd64 (1.5.0-2) ...
    Selecting previously unselected package libngtcp2-crypto-gnutls8:amd64.
    Preparing to unpack .../03-libngtcp2-crypto-gnutls8_1.5.0-2_amd64.deb ...
    Unpacking libngtcp2-crypto-gnutls8:amd64 (1.5.0-2) ...
    Preparing to unpack .../04-libcurl3t64-gnutls_8.8.0-2_amd64.deb ...
    Unpacking libcurl3t64-gnutls:amd64 (8.8.0-2) over (8.8.0-1) ...
    Preparing to unpack .../05-curl_8.8.0-2_amd64.deb ...
    Unpacking curl (8.8.0-2) over (8.8.0-1) ...
    Preparing to unpack .../06-libcurl4t64_8.8.0-2_amd64.deb ...
    Unpacking libcurl4t64:amd64 (8.8.0-2) over (8.8.0-1) ...
    Selecting previously unselected package liblua5.4-0:amd64.
    Preparing to unpack .../07-liblua5.4-0_5.4.6-3+b1_amd64.deb ...
    Unpacking liblua5.4-0:amd64 (5.4.6-3+b1) ...
    Preparing to unpack .../08-apache2_2.4.60-1_amd64.deb ...
    Unpacking apache2 (2.4.60-1) over (2.4.59-2) ...
    Preparing to unpack .../09-apache2-bin_2.4.60-1_amd64.deb ...
    Unpacking apache2-bin (2.4.60-1) over (2.4.59-2) ...
    Preparing to unpack .../10-apache2-data_2.4.60-1_all.deb ...
    Unpacking apache2-data (2.4.60-1) over (2.4.59-2) ...
    Preparing to unpack .../11-apache2-utils_2.4.60-1_amd64.deb ...
    Unpacking apache2-utils (2.4.60-1) over (2.4.59-2) ...
    Preparing to unpack .../12-libnbd0_1.20.2-1_amd64.deb ...
    Unpacking libnbd0 (1.20.2-1) over (1.20.1-1+b1) ...
    Setting up apt-utils (2.9.6) ...
    Setting up libcurl4t64:amd64 (8.8.0-2) ...
    Setting up libnbd0 (1.20.2-1) ...
    Setting up libnghttp3-9:amd64 (1.3.0-2) ...
    Setting up liblua5.4-0:amd64 (5.4.6-3+b1) ...
    Setting up libngtcp2-16:amd64 (1.5.0-2) ...
    Setting up apache2-data (2.4.60-1) ...
    Setting up libngtcp2-crypto-gnutls8:amd64 (1.5.0-2) ...
    Setting up apache2-utils (2.4.60-1) ...
    Setting up libcurl3t64-gnutls:amd64 (8.8.0-2) ...
    Setting up apache2-bin (2.4.60-1) ...
    Setting up curl (8.8.0-2) ...
    Setting up apache2 (2.4.60-1) ...
    apache-htcacheclean.service is a disabled or a static unit not running, not starting it.
    Processing triggers for ufw (0.36.2-6) ...
    Processing triggers for man-db (2.12.1-2) ...
    Processing triggers for libc-bin (2.38-13) ...
    root@lol ~ # apt autoremove
    REMOVING:                       
      liblua5.3-0
    
    Summary:
      Upgrading: 0, Installing: 0, Removing: 1, Not Upgrading: 0
      Freed space: 520 kB
    
    Continue? [Y/n] 
    (Reading database ... 98322 files and directories currently installed.)
    Removing liblua5.3-0:amd64 (5.3.6-2+b2) ...
    Processing triggers for libc-bin (2.38-13) ...
    root@lol ~ # 
    

    Afterwards:

    root@lol ~ # apt show liblua5.4-0
    Package: liblua5.4-0
    Version: 5.4.6-3+b1
    Priority: optional
    Section: libs
    Source: lua5.4 (5.4.6-3)
    Maintainer: Debian Lua Team <[email protected]>
    Installed-Size: 586 kB
    Depends: libc6 (>= 2.34), libstdc++6 (>= 4.1.1)
    Homepage: http://www.lua.org
    Tag: role::shared-lib
    Download-Size: 147 kB
    APT-Manual-Installed: no
    APT-Sources: http://deb.debian.org/debian unstable/main amd64 Packages
    Description: Shared library for the Lua interpreter version 5.4
     Lua is a powerful, light-weight programming language designed for extending
     applications.  The language engine is accessible as a library, having a C
     API which allows the application to exchange data with Lua programs and also
     to extend Lua with C functions.  Lua is also used as a general-purpose,
     stand-alone language through the simple command line interpreter provided.
     .
     This package contains runtime libraries.  You shouldn't need to install it
     explicitly.
    
    root@lol ~ # 
    
  • Not_OlesNot_Oles Member, Patron Provider

    Google Gemini wrote a program in response to my request to compare time taken to write "hello world" 10,000 times to /dev/null in C versus in Lua from C versus in Python from C. Here is the program, the compile command, and the result in case anybody might be interested. No claim that the program makes sense and no claim that the result is meaningful. :) But it definitely was fun messing with this program! :)

    root@lol ~/c-lua-python # cat hello_world_files.c # Version 5
    #include <stdio.h>
    #include <lua.h>
    #include <lauxlib.h>
    #include <lualib.h>
    #include <Python.h>
    #include <time.h>  
    
    #define NUM_ITERATIONS 10000 // Increased iterations
    
    // Function to measure execution time with an additional void pointer argument
    double measure_time(void (*func)(void *), void *arg) {
        clock_t start, end;
        double cpu_time_used;
    
        start = clock();
        func(arg); // Call the function with its argument
        end = clock();
        cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC;
        return cpu_time_used;
    }
    
    // Function to write "hello world" to /dev/null using C 
    void write_hello_c() {
        FILE *dev_null = fopen("/dev/null", "w");
        for (int i = 0; i < NUM_ITERATIONS; i++) {
            fprintf(dev_null, "hello world from C\n");
        }
        fclose(dev_null);
    }
    
    // Corrected Lua function
    void write_hello_lua(void *arg) {
        lua_State *L = (lua_State *)arg;  
        char lua_script[200];  // Increased size for the Lua script
        snprintf(lua_script, sizeof(lua_script), "for i = 1, %d do local devnull = io.open('/dev/null', 'w') devnull:write('hello world from Lua\\n') devnull:close() end", NUM_ITERATIONS);
    
        if (luaL_loadstring(L, lua_script) != LUA_OK) {
            fprintf(stderr, "Error: %s\n", lua_tostring(L, -1));
        }
    
        lua_pcall(L, 0, 0, 0);
    }
    
    // Function to write "hello world" to /dev/null using Python
    void write_hello_python() {
        PyRun_SimpleString(
            "import os\n" // Add import statement for os
            "for i in range(10000):\n"
            "    print('hello world from Python', file=open(os.devnull, 'w'))" 
        );
    }
    
    int main() {
        lua_State *L = luaL_newstate();
        luaL_openlibs(L);
    
        Py_Initialize();
    
        // Open /dev/null before timing
        FILE *dev_null = fopen("/dev/null", "w");
    
        double c_time = measure_time(write_hello_c, NULL); 
        double lua_time = measure_time(write_hello_lua, L);  
        double python_time = measure_time(write_hello_python, NULL); 
    
        // Close resources
        fclose(dev_null);
        lua_close(L);
        Py_Finalize();
    
        // Measure and print times
        printf("C average time: %f seconds\n", c_time);
        printf("Lua average time: %f seconds\n", lua_time);
        printf("Python average time: %f seconds\n", python_time);
    
        return 0;
    }
    root@lol ~/c-lua-python # 
    
    root@lol ~/c-lua-python # gcc -o hello_world_files hello_world_files.c -I/usr/include/python3.12 -L/usr/lib/python3.12 -lpython3.12 -I/usr/include/lua5.3 -llua5.3
    
    root@lol ~/c-lua-python # time ./hello_world_files 
    C average time: 0.000065 seconds
    Lua average time: 0.015810 seconds
    Python average time: 0.050548 seconds
    
    real    0m0.081s
    user    0m0.045s
    sys     0m0.037s
    root@lol ~/c-lua-python # date
    Thu Jul  4 02:22:26 AM UTC 2024
    root@lol ~/c-lua-python # 
    
  • edited July 2024

    Nice. Maybe you could try compiling against LuaJit (https://packages.debian.org/sid/libluajit-5.1-dev) to see how much of a difference it'll make (in theory it should be even faster than default Lua - might not really do much here due to being bound by startup time though)?

    LuaJit should be API compatible to standard Lua so all you'll have to change is the library you compile against (-I/usr/include/luajit-2.1 instead of -I/usr/include/lua5.3 and -lluajit-5.1 instead of -llua5.3 - don't ask me why the library is called 5.1 when it's really version 2.1...).

    Thanked by 1Not_Oles
  • Not_OlesNot_Oles Member, Patron Provider

    @totally_not_banned Thanks for your comment! I will try it, probably tomorrow or the next day. I will post the results here. Thanks again!

    Thanked by 1totally_not_banned
  • Not_OlesNot_Oles Member, Patron Provider
    root@lol ~ # date; apt-get upgrade
    Fri Jul  5 08:38:11 PM UTC 2024
    
      [ . . . ]
    
    The following packages will be upgraded:
      libc-bin libc-dev-bin libc-l10n libc6 libc6-dev libluajit-5.1-2 libluajit-5.1-common locales
      usb.ids
    
      [ . . . ]
    
    Do you want to continue? [Y/n] 
    
      [ . . . ]
    
    root@lol ~ # apt show libluajit-5.1-dev
    Package: libluajit-5.1-dev
    Version: 2.1.0+openresty20240626-1
    Priority: optional
    Section: libdevel
    Source: luajit
    Maintainer: Debian Lua Team <[email protected]>
    Installed-Size: 811 kB
    Provides: libluajit-5.1.so
    Depends: libluajit-5.1-2 (= 2.1.0+openresty20240626-1)
    Conflicts: libluajit2-5.1-dev
    Replaces: libluajit2-5.1-dev
    Homepage: https://github.com/openresty/luajit2
    Tag: devel::library, role::devel-lib
    Download-Size: 279 kB
    APT-Sources: http://deb.debian.org/debian unstable/main amd64 Packages
    Description: OpenResty-maintained branch of LuaJIT (development files)
     This package contains header files and a statically linkable library for
     LuaJIT.
    
    root@lol ~ # apt-get install libluajit-5.1-dev
    Reading package lists... Done
    Building dependency tree... Done
    Reading state information... Done
    The following NEW packages will be installed:
      libluajit-5.1-dev
    0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
    Need to get 279 kB of archives.
    After this operation, 811 kB of additional disk space will be used.
    Get:1 http://deb.debian.org/debian unstable/main amd64 libluajit-5.1-dev amd64 2.1.0+openresty20240626-1 [279 kB]
    Fetched 279 kB in 0s (22.9 MB/s)      
    Selecting previously unselected package libluajit-5.1-dev:amd64.
    (Reading database ... 98649 files and directories currently installed.)
    Preparing to unpack .../libluajit-5.1-dev_2.1.0+openresty20240626-1_amd64.deb ...
    Unpacking libluajit-5.1-dev:amd64 (2.1.0+openresty20240626-1) ...
    Setting up libluajit-5.1-dev:amd64 (2.1.0+openresty20240626-1) ...
    root@lol ~ # 
    

    I guess this looks okay. In particular, for the present context, I guess there is no problem with the above listed conflict with libluajit2-5.1-dev.

    Does anybody see any issues / something I am missing? Thanks!

  • Not_OlesNot_Oles Member, Patron Provider

    @Not_Oles said: root@lol ~/c-lua-python # gcc -o hello_world_files hello_world_files.c -I/usr/include/python3.12 -L/usr/lib/python3.12 -lpython3.12 -I/usr/include/lua5.3 -llua5.3

    @totally_not_banned said: so all you'll have to change is the library you compile against (-I/usr/include/luajit-2.1 instead of -I/usr/include/lua5.3 and -lluajit-5.1 instead of -llua5.3 - don't ask me why the library is called 5.1 when it's really version 2.1...).

    So does it look right that the compile command should become:

    gcc -O hello_world_files hello_world_files.c -I/usr/include/python3.12 -L/usr/lib/python3.12 -lpython3.12 -I/usr/include/luajit-2.1 -lluajit-5.1

    Thanks!

  • Not_OlesNot_Oles Member, Patron Provider

    Made a new luajit directory, copied the C source file, and renamed it to add its version, which is 4. When I try to compile, gcc throws no error, but seemingly fails to produce output. ld throws an error. What's up?

    root@lol ~/c-luajit-python # date
    Fri Jul  5 09:19:49 PM UTC 2024
    root@lol ~/c-luajit-python # ls -l
    total 8
    -rw-r--r-- 1 root root  149 Jul  5 21:17 compile-command
    -rw-r--r-- 1 root root 2177 Jul  4 02:15 hello_world_files-4.c
    root@lol ~/c-luajit-python # cat hello_world_files-4.c 
    #include <stdio.h>
    #include <lua.h>
    #include <lauxlib.h>
    #include <lualib.h>
    #include <Python.h>
    #include <time.h>  
    
    #define NUM_ITERATIONS 10000 // Increased iterations
    
    // Function to measure execution time with an additional void pointer argument
    double measure_time(void (*func)(void *), void *arg) {
        clock_t start, end;
        double cpu_time_used;
    
        start = clock();
        func(arg); // Call the function with its argument
        end = clock();
        cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC;
        return cpu_time_used;
    }
    
    // Function to write "hello world" to /dev/null using C 
    void write_hello_c() {
        FILE *dev_null = fopen("/dev/null", "w");
        for (int i = 0; i < NUM_ITERATIONS; i++) {
            fprintf(dev_null, "hello world from C\n");
        }
        fclose(dev_null);
    }
    
    // Function to write "hello world" to /dev/null using Lua, accepting void pointer argument
    void write_hello_lua(void *arg) {
        lua_State *L = (lua_State *)arg;
        char lua_script[100];  
        snprintf(lua_script, sizeof(lua_script), "local devnull = io.open('/dev/null', 'w') for i = 1, %d do devnull:write('hello world from Lua\\n') end devnull:close()", NUM_ITERATIONS);
    
        if (luaL_loadstring(L, lua_script) != LUA_OK) {
            fprintf(stderr, "Error: %s\n", lua_tostring(L, -1));
        }
    
        lua_pcall(L, 0, 0, 0);
    }
    
    // Function to write "hello world" to /dev/null using Python
    void write_hello_python() {
        PyRun_SimpleString(
            "import os\n" // Add import statement for os
            "for i in range(10000):\n"
            "    print('hello world from Python', file=open(os.devnull, 'w'))" 
        );
    }
    
    int main() {
        lua_State *L = luaL_newstate();
        luaL_openlibs(L);
    
        Py_Initialize();
    
        double c_time = measure_time(write_hello_c, NULL); 
        double lua_time = measure_time(write_hello_lua, L);  
        double python_time = measure_time(write_hello_python, NULL); 
    
        // Close resources
        lua_close(L);
        Py_Finalize();
    
        // Measure and print times
        printf("C average time: %f seconds\n", c_time);
        printf("Lua average time: %f seconds\n", lua_time);
        printf("Python average time: %f seconds\n", python_time);
    
        return 0;
    }
    root@lol ~/c-luajit-python # cat compile-command 
    gcc -O hello_world_files -I/usr/include/python3.12 -L/usr/lib/python3.12 -lpython3.12 -I/usr/include/luajit-2.1 -lluajit-5.1 hello_world_files-4.c
    root@lol ~/c-luajit-python # $(cat compile-command)
    /usr/bin/ld: cannot find hello_world_files: No such file or directory
    collect2: error: ld returned 1 exit status
    root@lol ~/c-luajit-python #  ls -l
    total 8
    -rw-r--r-- 1 root root  149 Jul  5 21:17 compile-command
    -rw-r--r-- 1 root root 2177 Jul  4 02:15 hello_world_files-4.c
    root@lol ~/c-luajit-python # 
    
  • Not_OlesNot_Oles Member, Patron Provider

    Oh! Maybe the compile command is wrong. I mixed up optimization level (-O) and output file (-o). Let me try again. . . .

  • Not_OlesNot_Oles Member, Patron Provider
    root@lol ~/c-luajit-python # date
    Fri Jul  5 09:33:45 PM UTC 2024
    root@lol ~/c-luajit-python # cat compile-command 
    gcc -o hello_world_files -I/usr/include/python3.12 -L/usr/lib/python3.12 -lpython3.12 -I/usr/include/luajit-2.1 -lluajit-5.1 hello_world_files-4.c
    root@lol ~/c-luajit-python # $(cat compile-command)
    /usr/bin/ld: /tmp/ccfniiH2.o: in function `write_hello_lua':
    hello_world_files-4.c:(.text+0x107): undefined reference to `luaL_loadstring'
    /usr/bin/ld: hello_world_files-4.c:(.text+0x121): undefined reference to `lua_tolstring'
    /usr/bin/ld: hello_world_files-4.c:(.text+0x15d): undefined reference to `lua_pcall'
    /usr/bin/ld: /tmp/ccfniiH2.o: in function `write_hello_python':
    hello_world_files-4.c:(.text+0x178): undefined reference to `PyRun_SimpleStringFlags'
    /usr/bin/ld: /tmp/ccfniiH2.o: in function `main':
    hello_world_files-4.c:(.text+0x188): undefined reference to `luaL_newstate'
    /usr/bin/ld: hello_world_files-4.c:(.text+0x198): undefined reference to `luaL_openlibs'
    /usr/bin/ld: hello_world_files-4.c:(.text+0x19d): undefined reference to `Py_Initialize'
    /usr/bin/ld: hello_world_files-4.c:(.text+0x202): undefined reference to `lua_close'
    /usr/bin/ld: hello_world_files-4.c:(.text+0x207): undefined reference to `Py_Finalize'
    collect2: error: ld returned 1 exit status
    root@lol ~/c-luajit-python # 
    

    So, I showed these errors to a friend :) who suggested a few changes to the C source code. I will go try those changes. . . .

    Of course, we now lose the idea of running the identical C code calling lua and luajit.

  • edited July 2024

    It might also be related to the order of arguments used with GCC. I'm not 100% sure as i usually build in multiple steps (as in build object files first then link them together with libraries) but at least there order matters when resolving symbols and the fact it also fails to locate Python related symbols (nothing about them changed at all) is suspicious. Maybe try moving the hello_world_files-4.c argument after -o hello_world_files and see if this fixes things.

    Thanked by 1Not_Oles
  • Not_OlesNot_Oles Member, Patron Provider

    Here are a revised version of the program, a revised version of the compile command, and results of one run of the compiled binary.

    I am guessing that the changes to the includes in the C code to accommodate LuaJIT are insignificant to the results. Maybe we could add the non-JIT, regular Lua interpreter includes a long with the JIT includes, detect or add an option to specify whether JIT or non-JIT was being used, and thus run the exact same code with both the regular Lua interpreter or LuaJIT.

    I saw what seemed to be significant variations of the times in the output of multiple runs of a previous version of the code. So let's not put much faith in the results obtained in any single run. Maybe, if anyone is interested to try multiple runs, and make a guess about the causes of variations, that might be fun.

    root@lol ~/c-luajit-python # cat hello_world_files-6-3.c
    #include <stdio.h>
    #include <luajit-2.1/lua.h>   // Include LuaJIT headers
    #include <luajit-2.1/lauxlib.h>
    #include <luajit-2.1/lualib.h>
    #include <Python.h>
    #include <time.h>  
    
    #define NUM_ITERATIONS 10000 // Increased iterations
    
    // Function to measure execution time with an additional void pointer argument
    double measure_time(void (*func)(void *), void *arg) {
        clock_t start, end;
        double cpu_time_used;
    
        start = clock();
        func(arg); // Call the function with its argument
        end = clock();
        cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC;
        return cpu_time_used;
    }
    
    // Function to write "hello world" to /dev/null using C 
    void write_hello_c() {
        FILE *dev_null = fopen("/dev/null", "w");
        for (int i = 0; i < NUM_ITERATIONS; i++) {
            fprintf(dev_null, "hello world from C\n");
        }
        fclose(dev_null);
    }
    
    // Function to write "hello world" to /dev/null using LuaJIT
    void write_hello_lua(void *arg) {
        lua_State *L = (lua_State *)arg;
        char lua_script[200];  
        snprintf(lua_script, sizeof(lua_script), "for i = 1, %d do local devnull = io.open('/dev/null', 'w') devnull:write('hello world from LuaJIT\\n') devnull:close() end", NUM_ITERATIONS);
    
        // Corrected LuaJIT script loading
        if (luaL_loadbuffer(L, lua_script, strlen(lua_script), "hello_world_lua") != LUA_OK) {  
            fprintf(stderr, "Error: %s\n", lua_tostring(L, -1));
        }
    
        lua_pcall(L, 0, 0, 0); // Execute the loaded LuaJIT script
    }
    
    // Function to write "hello world" to /dev/null using Python
    void write_hello_python() {
        PyRun_SimpleString(
            "import os\n" // Add import statement for os
            "for i in range(10000):\n"
            "    print('hello world from Python', file=open(os.devnull, 'w'))" 
        );
    }
    
    int main() {
        lua_State *L = luaL_newstate(); 
        luaL_openlibs(L);               
    
        Py_Initialize();
    
        double c_time = measure_time(write_hello_c, NULL); 
        double lua_time = measure_time(write_hello_lua, L);  
        double python_time = measure_time(write_hello_python, NULL); 
    
        // Close resources
        lua_close(L);
        Py_Finalize();
    
        // Measure and print times and calculate ratios
        printf("C average time: %f seconds\n", c_time);
        printf("LuaJIT average time: %f seconds\n", lua_time);
        printf("Python average time: %f seconds\n", python_time);
    
        if (c_time == 0 || lua_time == 0) {
            printf("Division by zero would occur, so no comparison is made.\n");
        } else {
            printf("C is %.2f times faster than LuaJIT\n", lua_time / c_time);
            printf("LuaJIT is %.2f times faster than Python\n", python_time / lua_time);
        }
    
        return 0;
    }
    root@lol ~/c-luajit-python # gcc -o hello_world_files hello_world_files-6-3.c -I/usr/include/python3.12 -L/usr/lib/python3.12 -lpython3.12 -I/usr/include/luajit-2.1 -lluajit-5.1 
    root@lol ~/c-luajit-python # date; time ./hello_world_files
    Fri Jul  5 10:23:37 PM UTC 2024
    C average time: 0.000118 seconds
    LuaJIT average time: 0.021028 seconds
    Python average time: 0.051364 seconds
    C is 178.20 times faster than LuaJIT
    LuaJIT is 2.44 times faster than Python
    
    real    0m0.096s
    user    0m0.072s
    sys     0m0.024s
    root@lol ~/c-luajit-python # 
    
    Thanked by 1totally_not_banned
  • edited July 2024

    Interesting. As for making the type of Lua optional, it's a little tricky since both libraries export the same symbols, so building against both of them will not work (at least without some serious voodoo magic and butchering the benchmark code). The most sane way would probably be to not link against the libraries at all but rather use dlopen to load either the default or the Jit version and then use dlsym to get the relevant function addresses. This would obviously need using variable function pointers for all Lua related functions (which are set to the results returned by dlsym).

    Shouldn't be that much work overall but might be a little confusing for people not used to the whole pointer thing. If there's some interest in this and there aren't any other takers (it's a nice exercise after all) i guess i could volunteer to do it ;)

  • Not_OlesNot_Oles Member, Patron Provider

    @totally_not_banned Below is me prompting Google Gemini:


    Here is hello_world_files-6.3.c, the compile command presently used, and the result of running the compiled program.

    root@lol ~/c-luajit-python # cat hello_world_files-6-3.c
    
    #include <stdio.h>
    
    #include <luajit-2.1/lua.h>   // Include LuaJIT headers
    
    #include <luajit-2.1/lauxlib.h>
    
    #include <luajit-2.1/lualib.h>
    
    #include <Python.h>
    
    #include <time.h>  
    
    
    
    #define NUM_ITERATIONS 10000 // Increased iterations
    
    
    
    // Function to measure execution time with an additional void pointer argument
    
    double measure_time(void (*func)(void *), void *arg) {
    
        clock_t start, end;
    
        double cpu_time_used;
    
    
    
        start = clock();
    
        func(arg); // Call the function with its argument
    
        end = clock();
    
        cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC;
    
        return cpu_time_used;
    
    }
    
    
    
    // Function to write "hello world" to /dev/null using C 
    
    void write_hello_c() {
    
        FILE *dev_null = fopen("/dev/null", "w");
    
        for (int i = 0; i < NUM_ITERATIONS; i++) {
    
            fprintf(dev_null, "hello world from C\n");
    
        }
    
        fclose(dev_null);
    
    }
    
    
    
    // Function to write "hello world" to /dev/null using LuaJIT
    
    void write_hello_lua(void *arg) {
    
        lua_State *L = (lua_State *)arg;
    
        char lua_script[200];  
    
        snprintf(lua_script, sizeof(lua_script), "for i = 1, %d do local devnull = io.open('/dev/null', 'w') devnull:write('hello world from LuaJIT\\n') devnull:close() end", NUM_ITERATIONS);
    
    
    
        // Corrected LuaJIT script loading
    
        if (luaL_loadbuffer(L, lua_script, strlen(lua_script), "hello_world_lua") != LUA_OK) {  
    
            fprintf(stderr, "Error: %s\n", lua_tostring(L, -1));
    
        }
    
    
    
        lua_pcall(L, 0, 0, 0); // Execute the loaded LuaJIT script
    
    }
    
    
    
    // Function to write "hello world" to /dev/null using Python
    
    void write_hello_python() {
    
        PyRun_SimpleString(
    
            "import os\n" // Add import statement for os
    
            "for i in range(10000):\n"
    
            "    print('hello world from Python', file=open(os.devnull, 'w'))" 
    
        );
    
    }
    
    
    
    int main() {
    
        lua_State *L = luaL_newstate(); 
    
        luaL_openlibs(L);               
    
    
    
        Py_Initialize();
    
    
    
        double c_time = measure_time(write_hello_c, NULL); 
    
        double lua_time = measure_time(write_hello_lua, L);  
    
        double python_time = measure_time(write_hello_python, NULL); 
    
    
    
        // Close resources
    
        lua_close(L);
    
        Py_Finalize();
    
    
    
        // Measure and print times and calculate ratios
    
        printf("C average time: %f seconds\n", c_time);
    
        printf("LuaJIT average time: %f seconds\n", lua_time);
    
        printf("Python average time: %f seconds\n", python_time);
    
    
    
        if (c_time == 0 || lua_time == 0) {
    
            printf("Division by zero would occur, so no comparison is made.\n");
    
        } else {
    
            printf("C is %.2f times faster than LuaJIT\n", lua_time / c_time);
    
            printf("LuaJIT is %.2f times faster than Python\n", python_time / lua_time);
    
        }
    
    
    
        return 0;
    
    }
    
    root@lol ~/c-luajit-python # gcc -o hello_world_files hello_world_files-6-3.c -I/usr/include/python3.12 -L/usr/lib/python3.12 -lpython3.12 -I/usr/include/luajit-2.1 -lluajit-5.1 
    
    root@lol ~/c-luajit-python # date; time ./hello_world_files
    
    Fri Jul  5 10:23:37 PM UTC 2024
    
    C average time: 0.000118 seconds
    
    LuaJIT average time: 0.021028 seconds
    
    Python average time: 0.051364 seconds
    
    C is 178.20 times faster than LuaJIT
    
    LuaJIT is 2.44 times faster than Python
    
    
    
    real    0m0.096s
    
    user    0m0.072s
    
    sys     0m0.024s
    
    root@lol ~/c-luajit-python # 
    

    Can you please make hello_world_files-7.0.c with luajit or regular Lua interpreter a command line option? My friend says: "Both libraries export the same symbols, so building against both of them will not work (at least without some serious voodoo magic and butchering the benchmark code). The most sane way would probably be to not link against the libraries at all but rather use dlopen to load either the default or the Jit version and then use dlsym to get the relevant function addresses. This would obviously need using variable function pointers for all Lua related functions (which are set to the results returned by dlsym)."


  • Not_OlesNot_Oles Member, Patron Provider

    Literally two seconds later, Gemini says the following:


    Absolutely! You and your friend are correct. It's indeed more flexible to make the choice of Lua interpreter (standard Lua or LuaJIT) a command-line option and use dynamic loading to avoid linking conflicts.

    Here's the revised hello_world_files-7.0.c that implements this approach, along with explanations:

    #include <stdio.h>
    #include <Python.h>
    #include <time.h>
    #include <dlfcn.h> // For dynamic library loading
    #include <string.h> // For string manipulation
    
    #define NUM_ITERATIONS 10000 // Increased iterations
    
    // Function pointers for Lua functions
    lua_CFunction luaL_newstate, luaL_openlibs, lua_close, luaL_loadbuffer, lua_pcall, lua_tostring;
    
    // Function to dynamically load Lua library
    int load_lua_library(const char *library_path) {
        void *handle = dlopen(library_path, RTLD_LAZY);
        if (!handle) {
            fprintf(stderr, "Error loading %s: %s\n", library_path, dlerror());
            return 1;
        }
    
        luaL_newstate = (lua_CFunction)dlsym(handle, "luaL_newstate");
        luaL_openlibs = (lua_CFunction)dlsym(handle, "luaL_openlibs");
        lua_close = (lua_CFunction)dlsym(handle, "lua_close");
        luaL_loadbuffer = (lua_CFunction)dlsym(handle, "luaL_loadbuffer");
        lua_pcall = (lua_CFunction)dlsym(handle, "lua_pcall");
        lua_tostring = (lua_CFunction)dlsym(handle, "lua_tostring");
    
        if (!luaL_newstate || !luaL_openlibs || !lua_close || !luaL_loadbuffer || !lua_pcall || !lua_tostring) {
            fprintf(stderr, "Error getting Lua functions: %s\n", dlerror());
            return 1;
        }
    
        return 0;
    }
    
    // Function to measure execution time
    double measure_time(void (*func)(void *), void *arg) {
        // ... (same as before) ...
    }
    
    // Function to write "hello world" to /dev/null using C 
    void write_hello_c() {
        // ... (same as before) ...
    }
    
    // Function to write "hello world" to /dev/null using loaded Lua implementation
    void write_hello_lua(void *arg) {
        lua_State *L = (lua_State *)arg;
        char lua_script[200];
        snprintf(lua_script, sizeof(lua_script), "for i = 1, %d do local devnull = io.open('/dev/null', 'w') devnull:write('hello world from %s\\n') devnull:close() end", NUM_ITERATIONS, (char*)arg); // Print Lua or LuaJIT
    
        if (luaL_loadbuffer(L, lua_script, strlen(lua_script), "hello_world_lua") != LUA_OK) {
            fprintf(stderr, "Error: %s\n", lua_tostring(L, -1));
        }
    
        lua_pcall(L, 0, 0, 0); // Execute the loaded Lua script
    }
    
    // Function to write "hello world" to /dev/null using Python
    void write_hello_python() {
        // ... (same as before) ...
    }
    
    int main(int argc, char *argv[]) {
        if (argc != 2 || (strcmp(argv[1], "lua") != 0 && strcmp(argv[1], "luajit") != 0)) {
            fprintf(stderr, "Usage: %s [lua|luajit]\n", argv[0]);
            return 1;
        }
    
        const char *lua_lib = strcmp(argv[1], "lua") == 0 ? "liblua5.3.so" : "libluajit-5.1.so.2";
        if (load_lua_library(lua_lib) != 0) {
            return 1;
        }
    
        lua_State *L = luaL_newstate(); 
        luaL_openlibs(L);               
    
        Py_Initialize();
    
        double c_time = measure_time(write_hello_c, NULL); 
        double lua_time = measure_time(write_hello_lua, (void*)argv[1]); // Pass library name as arg to Lua function 
        double python_time = measure_time(write_hello_python, NULL); 
    
        // Close resources
        lua_close(L);
        Py_Finalize();
    
        // Measure and print times and calculate ratios
        printf("C average time: %f seconds\n", c_time);
        printf("%s average time: %f seconds\n", argv[1], lua_time); // Use command-line argument for Lua type
        printf("Python average time: %f seconds\n", python_time);
    
        if (c_time == 0 || lua_time == 0) {
            printf("Division by zero would occur, so no comparison is made.\n");
        } else {
            printf("C is %.2f times faster than %s\n", lua_time / c_time, argv[1]);
            printf("%s is %.2f times faster than Python\n", argv[1], python_time / lua_time);
        }
    
        return 0;
    }
    

    Key Changes:

    • Dynamic Loading:

    dlopen, dlsym, and dlclose are used to dynamically load the Lua library specified on the command line.

    • Function Pointers:

    Function pointers (luaL_newstate, luaL_openlibs, etc.) are used to store the addresses of the dynamically loaded Lua functions.

    • Command-line Argument:

    The main function now takes command-line arguments. The first argument (argv[1]) is expected to be either "lua" or "luajit" to specify which Lua implementation to use.

    • Conditional Library Loading:

    The load_lua_library function loads the appropriate Lua library (liblua5.3.so or libluajit-5.1.so.2) based on the command-line argument.


  • Not_OlesNot_Oles Member, Patron Provider

    Lots of errors appear when compiling. Gemini is going through multiple revisions, and, at least, the number of errors is being reduced. . . .

  • edited July 2024

    @Not_Oles said:
    Lots of errors appear when compiling. Gemini is going through multiple revisions, and, at least, the number of errors is being reduced. . . .

    Wow, it's already crazy/scary enough how much it can figure out but if it doesn't succeed in coming up with a working version just ping me. From skimming the code it looks like it messes up giving the function pointers correct type declarations (it uses the lua_CFunction type for all of them when the functions take very different parameters, which obviously won't work - like for example luaL_newstate takes zero parameters while luaL_loadbuffer takes 4). There might be other things too but this sticks out the most during a quick glance.

    Thanked by 1Not_Oles
  • Not_OlesNot_Oles Member, Patron Provider

    Gemini and I kept going through many more versions. Finally we mutually decided to give up on the idea of combining Lua Interpreter and LuaJIT in the single program. Gemini wanted to simplify by writing two separate programs, one comparing C, Lua, and Python, and the other comparing C, LuaJIT, and Python. Here is the first of the two programs, the compile command, and the output.

    root@lol ~/c-luajit-python # cat -n hello_world_files_lua-9.0.c
         1  #include <stdio.h>
         2  #include <string.h>  // for strcmp, strlen
         3  #include <time.h>    // for clock, CLOCKS_PER_SEC
         4  #include <Python.h>  // for Python C API
         5
         6  #include <lua5.3/lua.h>
         7  #include <lua5.3/lauxlib.h>
         8  #include <lua5.3/lualib.h>   
         9
        10  #define NUM_ITERATIONS 10000 // Increased iterations
        11
        12  // Function prototypes (forward declarations)
        13  void write_hello_c();
        14  void write_hello_python();
        15
        16  // Function to measure execution time with an additional void pointer argument
        17  double measure_time(void (*func)(void *), void *arg) {
        18      clock_t start, end;
        19      double cpu_time_used;
        20
        21      start = clock();
        22      func(arg); // Call the function with its argument
        23      end = clock();
        24      cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC;
        25      return cpu_time_used;
        26  }
        27
        28  // Function to write "hello world" to /dev/null using C 
        29  void write_hello_c() {
        30      FILE *dev_null = fopen("/dev/null", "w");
        31      for (int i = 0; i < NUM_ITERATIONS; i++) {
        32          fprintf(dev_null, "hello world from C\n");
        33      }
        34      fclose(dev_null);
        35  }
        36
        37
        38  // Function to write "hello world" to /dev/null using Lua
        39  void write_hello_lua() {
        40      lua_State *L = luaL_newstate(); 
        41      luaL_openlibs(L);               
        42      
        43      // Open devnull outside of the loop
        44      luaL_loadstring(L, "devnull = io.open('/dev/null', 'w')");  // Open /dev/null before the loop
        45      lua_pcall(L, 0, 0, 0);
        46
        47      char lua_script[200];
        48      snprintf(lua_script, sizeof(lua_script), "for i = 1, %d do devnull:write('hello world from Lua\\n') end", NUM_ITERATIONS);
        49     
        50      if (luaL_loadbuffer(L, lua_script, strlen(lua_script), "hello_world_lua") != LUA_OK) {
        51          fprintf(stderr, "Error: %s\n", lua_tostring(L, -1));
        52      }
        53
        54      lua_pcall(L, 0, 0, 0); // Execute the loaded Lua script
        55
        56      // Close devnull after the loop
        57      luaL_loadstring(L, "devnull:close()"); // Close /dev/null after the loop
        58      lua_pcall(L, 0, 0, 0);
        59
        60      lua_close(L);
        61  }
        62
        63  // Function to write "hello world" to /dev/null using Python
        64  void write_hello_python() {
        65      PyRun_SimpleString(
        66          "import os\n" // Add import statement for os
        67          "for i in range(10000):\n"
        68          "    print('hello world from Python', file=open(os.devnull, 'w'))" 
        69      );
        70  }
        71
        72  int main(int argc, char *argv[]) {
        73      (void)argc; // unused parameter
        74      (void)argv; // unused parameter
        75
        76      Py_Initialize();
        77      
        78      double c_time = measure_time(write_hello_c, NULL); 
        79      double lua_time = measure_time(write_hello_lua, NULL); 
        80      double python_time = measure_time(write_hello_python, NULL); 
        81      
        82      Py_Finalize();
        83
        84      // Measure and print times and calculate ratios
        85      printf("C average time: %f seconds\n", c_time);
        86      printf("Lua average time: %f seconds\n", lua_time); 
        87      printf("Python average time: %f seconds\n", python_time);
        88
        89      if (c_time == 0 || lua_time == 0) {
        90          printf("Division by zero would occur, so no comparison is made.\n");
        91      } else {
        92          printf("C is %.2f times faster than Lua\n", lua_time / c_time);
        93          printf("Lua is %.2f times faster than Python\n", python_time / lua_time);
        94      }
        95
        96      return 0;
        97  }
        98
    root@lol ~/c-luajit-python # gcc -o hello_world_files_lua hello_world_files_lua-9.0.c -I/usr/inclu
    de/python3.12 -L/usr/lib/python3.12 -lpython3.12 -llua5.3
    root@lol ~/c-luajit-python # ./hello_world_files_lua 
    C average time: 0.000112 seconds
    Lua average time: 0.000797 seconds
    Python average time: 0.058817 seconds
    C is 7.12 times faster than Lua
    Lua is 73.80 times faster than Python
    root@lol ~/c-luajit-python # 
    

    Working on the second program with LuaJIT. . . .

  • Not_OlesNot_Oles Member, Patron Provider
    root@lol ~/c-luajit-python # ed hello_world_files_luajit-9.1.c
    hello_world_files_luajit-9.1.c: No such file or directory
    a
    #include <stdio.h>
    #include <string.h>  // for strlen
    #include <time.h>    // for clock, CLOCKS_PER_SEC
    #include <Python.h>  // for Python C API
    
    #include <luajit-2.1/lua.h>   // Include LuaJIT headers
    #include <luajit-2.1/lauxlib.h>
    #include <luajit-2.1/lualib.h>
    
    #define NUM_ITERATIONS 10000 // Number of iterations for each language
    
    // Function to measure execution time with an additional void pointer argument
    double measure_time(void (*func)(void *), void *arg) {
        clock_t start, end;
        double cpu_time_used;
    
        start = clock();
        func(arg); // Call the function with its argument
        end = clock();
        cpu_time_used = ((double) (end - start)) / CLOCKS_PER_SEC;
        return cpu_time_used;
    }
    
    // Function to write "hello world" to /dev/null using C 
    void write_hello_c() {
        FILE *dev_null = fopen("/dev/null", "w");
        for (int i = 0; i < NUM_ITERATIONS; i++) {
            fprintf(dev_null, "hello world from C\n");
        }
        fclose(dev_null);
    }
    
    // Function to write "hello world" to /dev/null using LuaJIT
    void write_hello_lua() {
        lua_State *L = luaL_newstate(); 
        luaL_openlibs(L);               
    
        // Open devnull outside of the loop
        luaL_loadstring(L, "devnull = io.open('/dev/null', 'w')");  
        lua_pcall(L, 0, 0, 0);
    
        char lua_script[200];
        snprintf(lua_script, sizeof(lua_script), "for i = 1, %d do devnull:write('hello world from LuaJIT\\n') end", NUM_ITERATIONS);
    
        if (luaL_loadbuffer(L, lua_script, strlen(lua_script), "hello_world_lua") != LUA_OK) {
            fprintf(stderr, "Error: %s\n", lua_tostring(L, -1));
        }
    
        lua_pcall(L, 0, 0, 0);
    
        // Close devnull after the loop
        luaL_loadstring(L, "devnull:close()"); 
        lua_pcall(L, 0, 0, 0);
    
        lua_close(L);
    }
    
    // Function to write "hello world" to /dev/null using Python
    void write_hello_python() {
        PyRun_SimpleString(
            "import os\n"
            "for i in range(10000):\n"
            "    print('hello world from Python', file=open(os.devnull, 'w'))" 
        );
    }
    
    int main() {
    
        Py_Initialize();
    
        double c_time = measure_time(write_hello_c, NULL); 
        double lua_time = measure_time(write_hello_lua, NULL); 
        double python_time = measure_time(write_hello_python, NULL); 
    
        Py_Finalize();
    
        // Measure and print times and calculate ratios
        printf("C average time: %f seconds\n", c_time);
        printf("LuaJIT average time: %f seconds\n", lua_time); 
        printf("Python average time: %f seconds\n", python_time);
    
        if (c_time == 0 || lua_time == 0) {
            printf("Division by zero would occur, so no comparison is made.\n");
        } else {
            printf("C is %.2f times faster than LuaJIT\n", lua_time / c_time);
            printf("LuaJIT is %.2f times faster than Python\n", python_time / lua_time);
        }
    
        return 0;
    }
    .
    w
    2777
    q
    root@lol ~/c-luajit-python # gcc -o hello_world_files_luajit hello_world_files_luajit-9.1.c -I/usr/include/python3.12 -L/usr/lib/python3.12 -lpython3.12 -lluajit-5.1
    root@lol ~/c-luajit-python # ./hello_world_files_luajit 
    C average time: 0.000072 seconds
    LuaJIT average time: 0.000186 seconds
    Python average time: 0.053127 seconds
    C is 2.58 times faster than LuaJIT
    LuaJIT is 285.63 times faster than Python
    root@lol ~/c-luajit-python # 
    
  • Not_OlesNot_Oles Member, Patron Provider

    @Not_Oles said:

    C is 7.12 times faster than Lua

    @Not_Oles said:

    C is 2.58 times faster than LuaJIT

    Pretty soon LuaJIT is going to catch up to C! /s

    No claim that this code or these results are correct!

    Unless somebody has a comment or a question I am going to move on to a new project. Thanks to @totally_not_banned for friendly help and friendly support!

  • @Not_Oles said:

    @Not_Oles said:

    C is 7.12 times faster than Lua

    @Not_Oles said:

    C is 2.58 times faster than LuaJIT

    Pretty soon LuaJIT is going to catch up to C! /s

    Hehehe, maybe? Who knows? In any case it's impressively fast for such a little scripting language.

    No claim that this code or these results are correct!

    Well, at least the result (LuaJit being faster than default Lua) is what would be expected, so chances are that even if it isn't 100% spot on it's pretty close.

    Unless somebody has a comment or a question I am going to move on to a new project. Thanks to @totally_not_banned for friendly help and friendly support!

    Any time. It's kinda cool to see Lua beat Python (which is a way more popular language) by such a big margin :)

Sign In or Register to comment.