lua

Cのブリッジライブラリからテーブルを受け取る

今まで、lua_pushstringして文字列を取得する形でしか使って来なかったのですが、テーブルを受け取りたくなったのでやってみました。


static int test(lua_State *L)
{
  const char *str = luaL_checkstring(L, 1);
  int i;

  lua_newtable(L);
  for ( i=0; i<4; i++ ) {
    lua_pushstring(L, i + 1);
    lua_pushstring(L, (unsigned char *)str);
    lua_settable(L, -3);
  }

  return 1;
}

これでこんな感じで取れる

[“aaa”,”aaa”,”aaa”,”aaa”]

Cからluaにテーブル渡せるということは、いろいろCで実装出来るので便利。

hiredis使ってみた

luaでresty.redis使ってるんですが、どうも安定しないのでhiredisを使おうと思う。
まずはhsetとhgetallのサンプル書いて動作確認してみた。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <hiredis/hiredis.h>
 
int main(void) {
 
  char       *key1 = "aaaa";
  char       *key2 = "bbbb";
  char       *val  = "1111";
  redisReply *reply;
  int         i;
 
  redisContext *c = redisConnect("127.0.0.1", 6379);
  if (c->err) {
    printf("redisConnect Error: %s\n", c->errstr);
    return (-1);
  }
 
  // HSET                                                                                                                                                                           
  reply = redisCommand(c, "HSET %s %s %s", key1, key2, val);
  freeReplyObject(reply);
 
  // HGETALL                                                                                                                                                                        
  reply = redisCommand(c, "HGETALL %s", key1);
  if ( reply->type == REDIS_REPLY_ERROR ) {
    printf("redisCommand Error: %s\n", c->errstr);
  }
  else if (reply->type == REDIS_REPLY_ARRAY) {
    printf("hgetall: %s\n", key1);
    for ( i=0; i<reply->elements; i++ ) {
      if ( (i % 2) == 0 ) {
        printf("hkey: %s, ", reply->element[i]->str);
      }
      else {
        printf("value: %s\n", reply->element[i]->str);
      }
    }
  }
  freeReplyObject(reply);
 
  return (0);
}

$ ./a.out
hgetall: aaaa
hkey: bbbb, value: 1111

LuaJIT2をnginxで使うメモ

lua_resty_stringを使うのにLuaJIT2が必要だったので、インストールした時のメモ

LuaJIT2.0.0のインストール

$ wget http://luajit.org/download/LuaJIT-2.0.0.tar.gz
$ tar zxvf LuaJIT-2.0.0.tar.gz
$ cd LuaJIT-2.0.0
$ vi src/luaconf.h # 必要ならば定数の変更
$ make PREFIX=/usr/local/luajit
$ sudo make install PREFIX=/usr/local/luajit
$ vi /etc/ld.so.conf.d/luajit.conf
—–
/usr/local/luajit/lib
—–
$ sudo ldconfig

LuaJIT使用でnginxをコンパイル

$ cd /usr/local/src/nginx-1.2.6
$ export LUAJIT_LIB=/usr/local/luajit/lib
$ export LUAJIT_INC=/usr/local/luajit/include/luajit-2.0
$ ./configure -user=nginx –prefix=/usr/local/nginx_app -with-http_stub_status_module -add-module=../lua-nginx-module -with-http_ssl_module –-with-debug
$ make
$ sudo make install

速度比較 lua vs perl

luaには、厳密には配列は無く、テーブルという唯一のデータ構造で配列を実現しています。
連想配列のような感じですが、関数を入れて擬似的なクラスのように振る舞わせることもできます。
データ構造としては複雑そうで、単純な配列操作をした場合、遅いのではないかと疑問に思ったので、Perlと比較してみました。

等差数列の和を、わざと無駄なやり方で計算させてます(配列への代入と参照を毎回させています)

lua

local max = 10000000
local ary = {}
for i=1, max do
    if i > 1 then
        ary[i] = ary[i-1] + i
    else
        ary[i] = i;
    end
end
print(string.format("%d\n", ary[max]));

perl

my $max = 10000000;
my @ary = ();
for (1..$max) {
    if ($_ > 1) {
        $ary[$_] = $ary[$_ - 1] + $_;
    } else {
        $ary[$_] = $_;
    }
}
print sprintf("%d\n", $ary[$max]);

実行時間を計ってみた結果

$ time lua lua.lua
50000005000000

real 0m1.540s
user 0m0.782s
sys 0m0.426s

$ time perl perl.pl
50000005000000

real 0m5.031s
user 0m3.532s
sys 0m0.526s

杞憂でした。ダントツでluaの方が速かったです。
あとは文字列操作も気になるので、今度試してみます。

LUA_MAXCAPTURES

LUA_MAXCAPTURES
luaで、パターンマッチングの最大数を定義している定数

string.matchで、
too many captures
とエラーになるので、調べてみたら、マッチングの最大数が定数で定義されてた。

luaconf.hを下記のように編集して再コンパイルして解決

#define LUA_MAXCAPTURES 512