Im currently writing a small c program that makes repeated calls to lua functions in a tight loop - and im using luajit to speed things up. One of my requirements is to restrict the standard libraries available to the script. According to this answer, using lua_call to call luaopen_* is the way to do this, however this results in a massive performance hit over using luaL_openlibs.
A small test case of this:
test.c
// gcc -Wall -O3 -o test test.c -lm $(pkg-config --cflags --libs luajit)
#include <luajit.h>
#include <lualib.h>
#include <luaconf.h>
#include <lauxlib.h>
lua_State *LUA = NULL;
int lua_setup(char *filename) {
LUA = luaL_newstate();
// lua_pushcfunction(LUA, luaopen_math);
// lua_pushstring(LUA, LUA_MATHLIBNAME);
// lua_call(LUA, 1, 0);
luaL_openlibs(LUA);
luaL_loadfile(LUA, filename);
lua_pcall(LUA, 0, 0, 0);
return 1;
}
int main() {
lua_setup("test.lua");
for (int i = 0; i < 10000; i++) {
lua_getglobal(LUA, "test");
lua_call(LUA, 0, 1);
float ret = lua_tonumber(LUA, -1);
lua_pop(LUA, 1);
}
lua_close(LUA);
}
test.lua
function test()
r = 0
for i=0,10000 do
r = r + math.sin(i);
r = r % 2;
end
return r
end
results:
> time ./test
real 0m1.696s
user 0m1.650s
sys 0m0.000s
after replacing the luaL_openlibs with the commented-out lines
> time ./test
real 0m6.409s
user 0m6.239s
sys 0m0.004s
Could someone tell me why this occurs? Thanks.
Ok turns out im an idiot. Luajit includes a lua library that needs to be loaded. Adding the following fixed the problem.
lua_pushcfunction(LUA, luaopen_jit);
lua_pushstring(LUA, LUA_JITLIBNAME);
lua_call(LUA, 1, 0);
I'm trying to compile my C program using library Api of fluent-bit , but the header fluent-bit.h is missing and I don't understand why.
I installed fluent-bit using installation guide
Here is my code I want to test:
#include <fluent-bit.h>
int main()
{
int i;
int n;
char tmp[256];
flb_ctx_t *ctx;
int in_ffd;
int out_ffd;
/* Initialize library */
ctx = flb_create();
if (!ctx) {
exit(EXIT_FAILURE);
}
in_ffd = flb_input(ctx, "lib", NULL);
flb_input_set(ctx, in_ffd, "tag", "test", NULL);
out_ffd = flb_output(ctx, "stdout", NULL);
flb_output_set(ctx, out_ffd, "match", "test", NULL);
/* Start the background worker */
flb_start(ctx);
/* Push some data */
for (i = 0; i < 100; i++) {
n = snprintf(tmp, sizeof(tmp) - 1,
"[%f, {\"key\": \"val %i\"}]",
flb_time_now(), i);
flb_lib_push(ctx, in_ffd, tmp, n);
}
flb_stop(ctx);
/* Release Resources */
flb_destroy(ctx);
return 0;
}
Here the error I got:
hello.c:1:24: fatal error: fluent-bit.h: No such file or directory
#include <fluent-bit.h>
^
compilation terminated.
Problem solved, I didn't install fluent-bit and headers properly.
Here was the problem : the headers were missing, so move on to cd /path/to/downloaded/fluent-bit-x.y.z/includes
Then use
sudo cmake .
sudo make install
You'll get an output saying that the headers had been installed on your system.
To make sure fluent-bit is correctly installed too :
cd ..
sudo cmake .
sudo make install
You can now use the fluent-bit API without problems
I need help with memory profiling using JeMalloc.
I do the following things:
git clone https://github.com/jemalloc/jemalloc
cd jemalloc
./autogen.sh --enable-perf
make dist
make
sudo make install
export MALLOC_CONF=prof_leak:true,lg_prof_sample:0,prof_final:true
export LD_PRELOAD=/usr/local/Cellar/jemalloc/5.1.0/lib/libjemalloc.dylib
Then I run my application:
./some_executed_file
It is 100% that this binary file will use jemalloc
Because when I call
typedef struct {
char *cur;
char *end;
} MallocStatus;
static void GetJemallocStatus(void *mstat_arg, const char *status) {
MallocStatus *mstat = reinterpret_cast<MallocStatus *>(mstat_arg);
size_t status_len = status ? strlen(status) : 0;
size_t buf_size = (size_t)(mstat->end - mstat->cur);
if (!status_len || status_len > buf_size) {
return;
}
snprintf(mstat->cur, buf_size, "%s", status);
mstat->cur += status_len;
}
MallocStatus mstat;
const unsigned int kMallocStatusLen = 1000000;
std::unique_ptr<char[]> buf{new char[kMallocStatusLen + 1]};
mstat.cur = buf.get();
mstat.end = buf.get() + kMallocStatusLen;
je_malloc_stats_print(GetJemallocStatus, &mstat, "");
stats->append(buf.get());
I see JeMalloc statistics.
Regarding to
https://github.com/jemalloc/jemalloc/wiki/Use-Case:-Leak-Checking
I do everything correct - but I still don't see jeprof dump file do analyze memory leaks.
Thanks in advance.
Try adding prof:true,prof_active:true to your MALLOC_CONF, and using --enable-prof flag instead of --enable-perf.
Why would I need this?
The location of a datum keeps changing because input data varies too much, so other than printing it, sleeping for 30 seconds so I can manually enter it into GDB, then continuing the program, it might be useful to just let the program tell GDB where to watch.
But is such a thing possible?
You can get close; assuming for simplicity C/C++ language
Define a function that returns a reference to your datum to track:
// debug.h
extern "C" mydatastruct* GetDatumForDebug();
// debug.cpp
mydatastruct* GetDatumForDebug()
{
if (s_initialized)
return &some_complicated_address_lookup_perhaps_in_Cpp_or_java_orwhatever();
return (mydatastruct*) 0;
}
You can then subsequently just
(gdb) display GetDatumForDebug()
or even
(gdb) display GetDatumForDebug()->s
I assume it will be possible to use the result of GetDatumForDebug() in your debug watches, I'm not sure what you do/how you do that :)
Here is a working example, crammed in a single source (test.cpp) for speed: compile with g++ -g test.cpp -o test:
static bool s_initialized = false;
struct mydatastruct { const char* s; };
static mydatastruct& some_complicated_address_lookup_perhaps_in_Cpp_or_java_orwhatever()
{
static mydatastruct s_instance = { "hello world" };
s_initialized = true;
return s_instance;
}
extern "C" mydatastruct* GetDatumForDebug();
// debug.cpp
mydatastruct* GetDatumForDebug()
{
if (s_initialized)
return &some_complicated_address_lookup_perhaps_in_Cpp_or_java_orwhatever();
return (mydatastruct*) 0;
}
int main()
{
// force initialize for demo purpose:
some_complicated_address_lookup_perhaps_in_Cpp_or_java_orwhatever();
return 42;
}
Automate gdb commands
Append the following to .gdbinit in your working directory:
break main
run
call some_complicated_address_lookup_perhaps_in_Cpp_or_java_orwhatever()
display GetDatumForDebug()? GetDatumForDebug()->s : ""
This will automatically execute these commands on launching gdb in that directory
How to check whether a system is big endian or little endian?
In C, C++
int n = 1;
// little endian if true
if(*(char *)&n == 1) {...}
See also: Perl version
In Python:
from sys import byteorder
print(byteorder)
# will print 'little' if little endian
Another C code using union
union {
int i;
char c[sizeof(int)];
} x;
x.i = 1;
if(x.c[0] == 1)
printf("little-endian\n");
else printf("big-endian\n");
It is same logic that belwood used.
A one-liner with Perl (which should be installed by default on almost all systems):
perl -e 'use Config; print $Config{byteorder}'
If the output starts with a 1 (least-significant byte), it's a little-endian system. If the output starts with a higher digit (most-significant byte), it's a big-endian system. See documentation of the Config module.
In C++20 use std::endian:
#include <bit>
#include <iostream>
int main() {
if constexpr (std::endian::native == std::endian::little)
std::cout << "little-endian";
else if constexpr (std::endian::native == std::endian::big)
std::cout << "big-endian";
else
std::cout << "mixed-endian";
}
If you are using .NET: Check the value of BitConverter.IsLittleEndian.
In Rust (no crates or use statements required)
In a function body:
if cfg!(target_endian = "big") {
println!("Big endian");
} else {
println!("Little endian");
}
Outside a function body:
#[cfg(target_endian = "big")]
fn print_endian() {
println!("Big endian")
}
#[cfg(target_endian = "little")]
fn print_endian() {
println!("Little endian")
}
This is what the byteorder crate does internally: https://docs.rs/byteorder/1.3.2/src/byteorder/lib.rs.html#1877
In Powershell
[System.BitConverter]::IsLittleEndian
In Linux,
static union { char c[4]; unsigned long mylong; } endian_test = { { 'l', '?', '?', 'b' } };
#define ENDIANNESS ((char)endian_test.mylong)
if (ENDIANNESS == 'l') /* little endian */
if (ENDIANNESS == 'b') /* big endian */
A C++ solution:
namespace sys {
const unsigned one = 1U;
inline bool little_endian()
{
return reinterpret_cast<const char*>(&one) + sizeof(unsigned) - 1;
}
inline bool big_endian()
{
return !little_endian();
}
} // sys
int main()
{
if(sys::little_endian())
std::cout << "little";
}
In Rust (byteorder crate required):
use std::any::TypeId;
let is_little_endian = TypeId::of::<byteorder::NativeEndian>() == TypeId::of::<byteorder::LittleEndian>();
Using Macro,
const int isBigEnd=1;
#define is_bigendian() ((*(char*)&isBigEnd) == 0)
In C
#include <stdio.h>
/* function to show bytes in memory, from location start to start+n*/
void show_mem_rep(char *start, int n)
{
int i;
for (i = 0; i < n; i++)
printf("%2x ", start[i]);
printf("\n");
}
/*Main function to call above function for 0x01234567*/
int main()
{
int i = 0x01234567;
show_mem_rep((char *)&i, sizeof(i));
return 0;
}
When above program is run on little endian machine, gives “67 45 23 01” as output , while if it is run on big endian machine, gives “01 23 45 67” as output.
A compilable version of the top answer for n00bs:
#include <stdio.h>
int main() {
int n = 1;
// little endian if true
if(*(char *)&n == 1) {
printf("Little endian\n");
} else {
printf("Big endian\n");
}
}
Stick that in check-endianness.c and compile and run:
$ gcc -o check-endianness check-endianness.c
$ ./check-endianness
This whole command is a copy/pasteable bash script you can paste into your terminal:
cat << EOF > check-endianness.c
#include <stdio.h>
int main() {
int n = 1;
// little endian if true
if(*(char *)&n == 1) {
printf("Little endian\n");
} else {
printf("Big endian\n");
}
}
EOF
gcc -o check-endianness check-endianness.c \
&& ./check-endianness \
&& rm check-endianness check-endianness.c
The code is in a gist here if you prefer. There is also a bash command that you can run that will generate, compile, and clean up after itself.
In Nim,
echo cpuEndian
It is exported from the system module.
In bash (from How to tell if a Linux system is big endian or little endian?):
endian=`echo -n "I" | od -to2 | head -n1 | cut -f2 -d" " | cut -c6`
if [ "$endian" == "1" ]; then
echo "little-endian"
else
echo "big-endian"
fi
C logic to check whether your processor follows little endian or big endian
unsigned int i =12345;
char *c = (char *)&i; // typecast int to char* so that it points to first bit of int
if(*c != 0){ // If *c points to 0 then it is Big endian else Little endian
printf("Little endian");
}
else{
printf("Big endian");
}
Hope this helps. Was one of the question asked in my interview for the role of embedded software engineer role
All the answers using a program to find endianess at runtime is wrong! The fact whether a machine is big endian or little endian is hidden from the programmer, by the compiler. On a big-endian machine the typecast will again return 1, because the compiler knows that the machine is big endian and the casting will fetch the higher memory address. Only way to find the endianess is to fetch the system's configuration or environment variable. Similar to some of the answers above like the one liner perl answer etc.