有几种方案:
1、c++中嵌入quickjs,Javascript
2、c++中嵌入lua(这里选的是5.4版本)
3、rust中嵌入.net 6.0,也就是C#啦
先说下嵌入的方便程度,感觉lua是最容易嵌入的,在不同的操作系统上很容易就能一次编译成功,实际上lua也没有多少头(源)文件。quickjs要麻烦一些,在linux上就很容易编译,但是在Windows上有点麻烦,不支持msvc,最后是用了一个叫quickjspp的库,quickjspp的作者在quickjs上改了源码以适配msvc。嵌入.net 6.0,官网有教程,其实还好,跟着教程来,不过官网上的是用c++的,我这里改成了用rust,目前已经实现在windows和linux上运行,还实现了热重载的功能,可以在程序运行中卸载dll然后再重新加载dll。
性能对比,仅作为大概的不完全对比:
CPU: Intel(R) Core(TM) i7-8700 CPU @ 3.20GHz
c#: 6407毫秒
void Test()
{
int time = Environment.TickCount;
for (int i = 0; i < 45; i++)
{
Fib(i);
}
Console.WriteLine(Environment.TickCount - time);
}
int Fib(int n)
{
if (n <= 0)
return 0;
if (n < 3)
return 1;
return Fib(n - 1) + Fib(n - 2);
}
rust: 3657毫秒
fn fib(n: i32) -> i32 {
if n <= 0 {
return 0;
}
if n < 3 {
return 1;
}
return fib(n - 1) + fib(n - 2);
}
fn test() {
let current = SystemTime::now();
for i in 0..45 {
fib(i);
}
let duration = SystemTime::now()
.duration_since(current)
.unwrap()
.as_millis();
println!("{duration}");
}
Chrome V8 JS: 12465毫秒
quickjs:348006毫秒
function Fib(n)
{
if (n <= 0)
{
return 0;
}
if (n < 3)
return 1;
return Fib(n - 1) + Fib(n - 2);
}
let time = new Date().getTime();
for (let i = 0; i < 45; i++)
{
Fib(i);
}
let time1 = new Date().getTime();
console.log(time1 - time);
lua 5.4: 175.44秒
luajit2: 28.923秒
function fib(n)
if n <= 0 then
return 0
end
if n < 3 then
return 1
end
return fib(n - 1) + fib(n - 2)
end
function test()
local current = os.clock()
for i = 1,45 do
fib(i)
end
local duration = os.clock() - current
print(duration)
end
test()
c++17(msvc): 5982毫秒
int fib(int n)
{
if (n <= 0)
{
return 0;
}
if (n < 3)
return 1;
return fib(n - 1) + fib(n - 2);
}
std::function<long long()> getTime = []() {
std::chrono::steady_clock::time_point now = std::chrono::high_resolution_clock::now();
long long currentMilliseconds =
std::chrono::duration_cast<std::chrono::milliseconds>(now.time_since_epoch()).count();
return currentMilliseconds;
};
const long long time = getTime();
int a = 0;
for (int i = 0; i < 45; i++)
{
a = fib(i);
}
std::cout << getTime() - time << std::endl;
std::cout << a << std::endl;
这么对比下来,脚本语言没有JIT的加持,非常地慢呀