spacer.png, 0 kB
Erlang NIF tutorial

Yesterday Erlang version R13B03 (update: this article is now sligtly outdated. The NIFs in R14B have been simplified a little bit) was released and this version contained a major new addition to the language. Erlang now supports native implemented functions (NIFs) and are called like any other functions without any difference to the caller. The difference is in the implementation: pure C code, so it's pretty fast :)

I've decided to test the functions immediately. The results:

  • for trivial hello-world-functions, nif functions are slower than plain erlang functions, about 2-3x
  • BUT: when you are going to do anything mildly interesting, nifs are great. For example if you don't need the advanced features of erlang:now(), then writing your own version of now() as a NIF is much faster.


Some NIFs that I will start to use immediately:

  • mynif_now() : returns linux timestamp in seconds, based on time(0);
  • mynif_uniform(int scale) : return a random number between 1 and scale, just like random:uniform(N)
  • mynif_random() : returns a random number based on gettimeofday(&tv, NULL);

Example source code:

 
/* niftest.c */ 
#include "erl_nif.h" 
 
static ERL_NIF_TERM mynif_uniform(ErlNifEnv* env, ERL_NIF_TERM scale) { 
  struct timeval tv; 
  gettimeofday(&tv, NULL); 
  int ip; 
 
  if (!enif_get_int(env, scale, &ip)) //needs to be an integer 
  { 
    return enif_make_badarg(env); 
  }
  else if (ip<=1) //only allow >1 
  { 
    return enif_make_badarg(env); 
  } 
  else 
  { 
    return enif_make_int(env, (tv.tv_usec % ip)+1); 
  }
} 
 
static ERL_NIF_TERM mynif_random(ErlNifEnv* env) { 
  struct timeval tv; 
  gettimeofday(&tv, NULL); 
  return enif_make_int(env, tv.tv_usec); 
} 
 
static ERL_NIF_TERM mynif_now(ErlNifEnv* env) { 
  return enif_make_int(env, time(0)); 
} 
 
static ErlNifFunc nif_funcs[] = { 
  {"mynif_uniform", 1, mynif_uniform}, 
  {"mynif_random", 0, mynif_random}, 
  {"mynif_now", 0, mynif_now} 
  }; 
 
ERL_NIF_INIT(niftest,nif_funcs,NULL,NULL,NULL,NULL); 
 
to make:

gcc -fPIC -shared -o niftest.so niftest.c -I   /usr/local/lib/erlang/usr/include 

 

 
-module(niftest).
-module(niftest).
%-on_load(init/0).
-export([init/0, mynif_random/0, mynif_now/0, mynif_uniform/1, test_speed/2]).
 
init() ->
  case erlang:load_nif("./niftest", 0) of
    ok -> io:format("nif loaded ok~n",[]);
    {error, upgrade, Any} -> io:format("nif upgraded?: ~p~n", [Any]);
    Error -> io:format("nif init error: ~p~n", [Error])
  end.
 
mynif_random() ->
  "NIF library not loaded".
 
mynif_now() ->
  "NIF library not loaded".
 
mynif_uniform(N) ->
  "NIF library not loaded".

 

usage:

  • c(niftest).
  • niftest:mynif_uniform(10).
  • niftest:init().    
  • niftest:mynif_uniform(10).
Comments
Add New
+/-
Write comment
Name:
Email:
 
Website:
Title:
 
:angry::0:confused::cheer:B):evil::silly::dry::lol::kiss::D:pinch:
:(:shock::X:side::):P:unsure::woohoo::huh::whistle:;):s
:!::?::idea::arrow:
 
Please input the anti-spam code that you can read in the image.

3.26 Copyright (C) 2008 Compojoom.com / Copyright (C) 2007 Alain Georgette / Copyright (C) 2006 Frantisek Hliva. All rights reserved."

Last Updated ( Sunday, 21 November 2010 )
 
< Prev
spacer.png, 0 kB
rightborder
© 2006-2011 StartInChina.com - News and tips from Shenzhen, China