Poslua Blog

「你是一个出色的程序员」要比「你是一个开发总监」要有意义的多

Lua 排序算法 - 快速排序

Quick Sort

快速排序使用分治法(Divide and conquer)策略来把一个序列(list)分为两个子序列(sub-lists)。 分治法的基本思想是:将原问题分解为若干个规模更小但结构与原问题相似的子问题。递归地解这些子问题,然后将这些子问题的解组合为原问题的解。 算法步骤 从数列中挑出一个元素,称为 “基准”(pivot) 重新排序数列,所有元素比基准值小的摆放在基准前面,所有...

Lua 排序算法 - 冒泡排序

Bubble Sort

冒泡排序(Bubble Sort,台湾译为:泡沫排序或气泡排序)是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。 算法步骤 有一个长度为n的序列,一共需要n次外循环 在一次外循环里,...

Lua 的标准输出与缓存

最近我遇到了个奇怪的问题,我的一个 Lua 脚本需要通过 shell 的重定向将输出追加到一个日志文件中。但是那个 Lua 脚本的输出在日志文件里看来却不是实时的,输出的文本直到脚本结束时才能看到。 在 shell 下运行这个程序,是可以看到实时输出的: -- buffer_test.lua local socket = require "socket" local const = 1...

cjson 的抢占问题

默认的 cjson 其实是 “共享” 的

我说的 cjson 抢占 问题可不是 lua 的 非抢占 式协程,更准确的理解应该是:由于 lua 的协程切换,可能会导致 cjson 上下文不一致的情况。例如: -- json.lua local json = require("cjson") local _M = {} function _M.encode(data, empty_table_as_object) if j...

使用 newproxy 生成 userdata

原生的 Lua 也是可以生成 userdata 的

在 Lua 中,userdata 一般是在 C 里创建的数据结构,只能通过 C API 来操作。理论上 Lua 是不支持的,但是作者增加了一个隐藏的特性 newproxy 用于创建一个空的 userdata,参数可以选择是否带 metatable。主要是用来测试 GC,实现析构函数用的。 newproxy is an unsupported and undocumented func...

__len 其实很鸡肋

5.1 的 table 是不支持 __len 的

我们知道在 Lua 中取 table 的长度,可以使用 # 。但是这里有个前提,就是 table 必须是一个序列。如果一个 table 有「空洞」,那么用 # 取到的结果将没有明确含义!!! 但是根据 Lua 官方文档的说法,这个行为是可以通过 __len 元方法来改变的: A program can modify the behavior of the length operat...

Metatable 二三事

告别 Metatable 小白

对于很多 Luaer 来说,也许只有 table 才会有 metatable。其实这种认识是错误的。 实际上在 Lua 中,每个值都可以拥有一个元表。对 userdata 和 table 类型而言,其每个值都可以拥有独立的元表,也可以几个值共享一个元表。对于其他类型,一个类型的值共享一个元表。例如所有 number 类型的值会共享一个元表。而默认 Lua 只为 string 类型赋予了元表...

Lua 正确处理可变参数

一定要注意 table 中的 hole

为了在 Lua 里处理可变参数,我们可能会写下面这样的代码: local function args(...) if next({...}) then for _, v in ipairs{...} do print(v) end else print("empty var") end end ...

Lua string.find 中的 “坑”

我们的线上环境,ngx_lua api 都是以模块形式加载到 lua 级别的 vm 中,已达到最大性能。而且我们并没有使用传统的 “包” 的形式来加载(也就是 require "xx.xx.xx" ),而是直接以模块名为加载( require "xx" ),这就意味着我们需要不断的来动态设置 package.path 来配合 require 的机制。于是我们写了下面这个方法,来实现我们的需求...

OpenResty 中写日志的套路

记录日志很重要,套路同样更重要

在 OR 中为了方便调试,我们可能会用这样的方式来记录日志: local f = io.open("test.log", "a+") f:write(message .. "\n") f:close() 然而这种写法在大多数情况下,都是可以正常工作的。但是在高并发的系统上,尤其还是多 worker 的环境下,这样写日志是会串的,原因就是 io.open 自身的缓存机制(本质是 libc...