Kategorien
TeaScript (de)

TeaScript VS ChaiScript Fibonacci Benchmark (de)

Ich habe einen Benchmark in C++ zum Testen und Vergleichen von TeaScript und dem Wettbewerber ChaiScript im rekursiven Ausrechnen der Fibonacci Zahl 25 erstellt. Als Referenz habe ich dies auch noch in C++ gemacht. Der komplette Source Code des Benchmarks ist unten gelistet.

Das Ergebnis ist wirklich erstaunlich, da ich im Pre-Release 0.8.0 von TeaScript noch gar nicht „profiled“ und optimiert habe. Dies ist erst für ein späteres Pre-Release geplant.

(UPDATE 2023-01-17): Ich habe für diesen und allen zukünftigen Benchmarks für „Skriptsprachen in und für C++“ ein Github Repository erstellt.

Hier ist das Benchmark Ergebnis: Zeitmessung der Ausrechnung von fibonacci( 25 ) in Sekunden. Kürzer ist besser/schneller, länger ist langsamer.

Benchmark Ergebnis von Fibonacci( 25 )
Benchmark Ergebnis von Fibonacci( 25 )

Ein paar technische Infos zur Umgebung:
OS: Windows 10 21H2 (64bit)
CPU: Intel Core i7-11700
RAM: 32 GB
Compiler/Build: Visual Studio 2022 Community (17.4.3), Release/x64 (AVX2), C++20 (selben Settings wie in meinem Blog Post).

Ein paar Anmerkungen zu Python und Lua:
Python und Lua stehen derzeit aus Performanz-Sicht nicht im Wettbewerb zu TeaScript, da TeaScript als auch ChaiScript echte Skriptsprachen (und Header-Only C++ Libraries) sind, wohingegen Python und auch Lua den Source Code in einen Bytecode kompilieren und in einer virtuellen Stack-Maschine (Python) oder in einer noch komplexeren virtuellen Maschine (Lua) ausführen.

Dies mag sich in der Zukunft mit der Pro Version von TeaScript ändern.

Hier ist der C++ Quellcode des Benchmarks:

/*
 * SPDX-FileCopyrightText: Copyright (C) 2023 Florian Thake, <contact |the-at-symbol| tea-age.solutions>. All rights reserved.
 */
 
 
#include <cstdlib> // EXIT_SUCCESS
#include <cstdio>
#include <iostream>
#include <chrono>
 
#include <teascript/Parser.hpp>
#include <teascript/CoreLibrary.hpp>
 
#include <chaiscript/chaiscript.hpp>
 
// recursive fibonacci function in TeaScript
constexpr char tea_code[] = R"_SCRIPT_(
func fib( x ) {
   if( x == 1 or x == 0 ) {
      x
   } else {
      fib( x - 1 ) + fib( x - 2 )
   }
}
 
fib(25)
)_SCRIPT_";
 
// recursive fibonacci function in ChaiScript
constexpr char chai_code[] = R"_SCRIPT_(
def fib( x )
{
    if( x == 0 || x == 1 ) {
        return x;
    } else {
        return fib( x - 1 ) + fib( x - 2 );
    }
}
 
fib(25);
)_SCRIPT_";
 
auto Now()
{
    return std::chrono::steady_clock::now();
}
 
double CalcTimeInSecs( auto s, auto e )
{   
    std::chrono::duration<double> const  timesecs = e - s;
    return timesecs.count();
}
 
double exec_tea()
{
    teascript::Context c;
    teascript::CoreLibrary().Bootstrap( c );
    teascript::Parser  p;
    auto ast = p.Parse( tea_code );
    try {
        auto start  = Now();
        auto teares = ast->Eval( c );
        auto end    = Now();
 
        std::cout << "value: " << teares.GetAsLongLong() << std::endl;
 
        return CalcTimeInSecs( start, end );
 
    } catch( teascript::exception::runtime_error const &ex ) {
        teascript::util::pretty_print( ex );
    } catch( std::exception const &ex ) {
        puts( ex.what() );
    }
 
    return -1.0;
}
 
double exec_chai()
{
    chaiscript::ChaiScript chai;
    auto ast = chai.parse( chai_code );
    try {
        auto start = Now();
        auto chres = chai.eval( *ast );
        auto end   = Now();
 
        std::cout << "value: " << chaiscript::boxed_cast<int>(chres) << std::endl;
 
        return CalcTimeInSecs( start, end );
         
    } catch( chaiscript::Boxed_Value const &bv ) {
        puts( chaiscript::boxed_cast<chaiscript::exception::eval_error const &>(bv).what() );
    } catch( std::exception const &ex ) {
        puts( ex.what() );
    }
 
    return -1.0;
}
 
// recursive fibonacci function in C++
long long fib( long long x )
{
    if( x == 0 || x == 1 ) {
        return x;
    } else {
        return fib( x - 1 ) + fib( x - 2 );
    }
}
 
double exec_cpp()
{
    try {
        auto start = Now();
        auto res   = fib( 25 );
        auto end   = Now();
 
        std::cout << "value: " << res << std::endl;
 
        return CalcTimeInSecs( start, end );
 
    } catch( std::exception const &ex ) {
        puts( ex.what() );
    }
 
    return -1.0;
}
 
int main()
{
    std::cout << std::fixed;
    std::cout << std::setprecision( 8 );
 
    std::cout << "Benchmarking TeaScript and ChaiScript in calculating Fibonacci of 25...\n";
    std::cout << "... and C++ as a reference ... \n";
 
    std::cout << "\nStart Test C++" << std::endl;
    for( int i = 3; i != 0; --i ) {
        auto secs = exec_cpp();
        std::cout << "Calculation took: " << secs << " seconds." << std::endl;
    }
 
    std::cout << "\nStart Test TeaScript" << std::endl;
    for( int i = 3; i != 0; --i ) {
        auto secs = exec_tea();
        std::cout << "Calculation took: " << secs << " seconds." << std::endl;
    }
 
    std::cout << "\nStart Test ChaiScript" << std::endl;
    for( int i = 3; i != 0; --i ) {
        auto secs = exec_chai();
        std::cout << "Calculation took: " << secs << " seconds." << std::endl;
    }
 
    puts( "\n\nTest end." );
 
    return EXIT_SUCCESS;
}

… und hier der Screenshot des Durchlaufs:

Screenshot des Benchmarklaufs.
Screenshot des Benchmarklaufs.

Im Download Package von TeaScript ist übrigens auch (neben anderen Skripten) ein Skript zum Ausrechnen von Fibonacci Zahlen inklusive Zeitmessung enthalten.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert