月度存档: 三月 2014

mingw遇到的一个问题

自己的写一小段代码:

#include <stdio.h>
#include <string.h>
#include <lua.h>

int main(int argc,char* argv[]){
        lua_State* L=luaL_newstate();
        char tmp[1024];
        while(!feof(stdin)){
                fgets(tmp,sizeof(tmp),stdin);
                printf("%4lu %s\n",strlen(tmp),tmp);
        }
        return 0;
}

在win7 64位,mingw下编译总是报警告:

format '%lu' expects argument of type 'long unsigned int', but argument 2 has type 'size_t' [-Wformat=]    test3.c    /test7/src    line 18    C/C++ Problem

google了一下,试了各种方法,也无结果。
突然灵感一来,想起来mingw是32位系统,难道是因为这个原因,下载mingw64试下。

安装mingw64:http://sourceforge.net/projects/mingwbuilds/

 

ryzomcore 开源游戏代码

https://bitbucket.org/ryzom/ryzomcore

 

开始进行服务器调优,记录一下过程

开始进行服务器调优,记录一下过程,以便以后参考

1、服务器512M内存。mysql本地,日志rsyslog输出至远程。

2、直接往服务器发送10000个注册用户的请求,单socket,发送用了80毫秒,服务器处理完消耗89秒。

2.1) 关闭log后只需要27秒。但因为平时要使用log进行记录,不应该关闭log

2.2) 使用@Async标签,将db操作设置为异步,在dao上设置的@Async,未生效,处理时间还是一样长。

2.2) 1万个帐号注册只需要1分半,已经可以接受了。

3、测试1万帐号同时登陆。

3.1)需要同时开启10000个runnable,先试下同时开10000个socket的速度

3.2) 同时开始10000个socket,感觉速度还可以接受。

3.3)直接无限向服务器发送包,直接达到积累至几百万的消息包,先暂停优化。

3.3.1) 关闭log后,处理速度提升了两个数量级,发ping包,可以一次处理几十万也不会产生积累。但我写的机器人却卡死了,出现: GC overhead limit exceeded。jdk中自带的jvisualvm是个好东西。查找一下是哪里导致的挂掉。

3.4) 10000帐号同时并发登陆,好吧,直接卡死了。明天来解决。

3.5) 慢,非常慢。很耗时。

3.6) 猜测是否因为db读取慢的原因。测试db读取随机1万帐号只需要16秒。不是db读取的问题。

3.7) 打开日志,查看日志,发现一个现象:log处理中出现5秒的空白间隔,没有处理任何消息,经常出现。

3.8) 查找代码:

((InetSocketAddress) context.channel().remoteAddress()).getHostName();

问题出现在这里了,这里是阻塞方法,会去通过dns反查hostname。

修改为如下:

((InetSocketAddress) context.channel().remoteAddress()).getAddress().getHostAddress();

现在1万帐号登陆消耗38秒。

3.9 )  关闭日志后,1万帐号登陆只消耗11秒,已经可以接受了,上面测试的1万db读取需要16秒,这里更快是因为服务器是8线程同时处理登陆。

3.10) 关闭日志后,单socket发送1万帐号注册,处理完成31秒。这里有改进余地。暂时已经可以了。

3.11) 关闭日志后,多线程socket发送1万帐号注册,处理完成30秒。看这里主要是db io在消耗性能。

Ooyala分享的一篇技术文章 

http://www.jdon.com/45871

技术stack如下:
• Spray – high performance HTTP
• SLF4J / Logback
• Yammer Metrics
• spray-json
• Akka 2.x
• Scala 2.9 / 2.10

Android Asynchronous Http Client

loopj : http://loopj.com/android-async-http/

Android Asynchronous Http Client

scala工程创建

akka和scala学习。

都推荐使用sbt来进行管理。

sbt是一个类似maven的scala工具。

在项目目录下创建文件: build.sbt

至少要包含以下内容:

name := "hello"

version := "1.0"

scalaVersion := "2.10.3"

运行sbt,会自动在该目录下创建project文件夹:

在project文件夹下创建文件: plugins.sbt

addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "2.4.0")

重新运行sbt.

输入:eclipse

会自动将项目转为eclipse项目。

可以使用eclipse中的import功能导入项目,并且项目目录已经自动创建好了。

如果要改为akka项目,在build.sbt中添加以下两行:

resolvers += "Typesafe Repository" at "http://search.maven.org/"

libraryDependencies += "com.typesafe.akka" % "akka-actor_2.10" % "2.3.0"

学习下makefile

.PHONY : mingw ej2d linux undefined

CFLAGS = -g -Wall -Ilib -D EJOY2D_OS=$(OS)

// CFLAGS gcc接收的参数

// -g 生成调试信息,可用来gdb调试

// -Wall 输出gcc翻译时生成的警告信息

// -Ilib 将lib目录添加至编译查找路径,用来查找头文件

// gcc中命令行以tab开头

LDFLAGS :=

SRC := \
lib/shader.c \
lib/lshader.c \
lib/ejoy2dgame.c \
lib/fault.c \
lib/screen.c \
lib/texture.c \
lib/ppm.c \
lib/spritepack.c \
lib/sprite.c \
lib/lsprite.c \
lib/matrix.c \
lib/lmatrix.c \
lib/dfont.c \
lib/label.c \
lib/particle.c \
lib/lparticle.c \
lib/scissor.c

UNAME=$(shell uname)
SYS=$(if $(filter Linux%,$(UNAME)),linux,\
$(if $(filter MINGW%,$(UNAME)),mingw,\
$(if $(filter Darwin%,$(UNAME)),macosx,\
undefined\
)))

all: $(SYS)

undefined:
@echo “I can’t guess your platform, please do ‘make PLATFORM’ where PLATFORM is one of these:”
@echo ”      linux mingw macosx”

mingw : OS := WINDOWS
mingw : TARGET := ej2d.exe
mingw : CFLAGS += -I/usr/include -I/usr/local/include
mingw : LDFLAGS += -L/usr/bin -lgdi32 -lglew32 -lopengl32 -L/usr/local/bin -llua52
mingw : SRC += mingw/window.c mingw/winfw.c mingw/winfont.c

mingw : $(SRC) ej2d

linux : OS := LINUX
linux : TARGET := ej2d
linux : CFLAGS += -I/usr/include -I/usr/local/include $(shell freetype-config –cflags)
linux : LDFLAGS +=  -lGLEW -lGL -lX11 -lfreetype -llua -lm -Wl,-E
linux : SRC += posix/window.c posix/winfw.c posix/winfont.c

linux : $(SRC) ej2d

macosx : OS := MACOSX
macosx : TARGET := ej2d
macosx : CFLAGS += -I/usr/X11R6/include -I/usr/include -I/usr/local/include $(shell freetype-config –cflags) -D __MACOSX
macosx : LDFLAGS += -L/usr/X11R6/lib  -lGLEW -lGL -lX11 -lfreetype -llua -lm -Wl,-E -ldl
macosx : SRC += posix/window.c posix/winfw.c posix/winfont.c

macosx : $(SRC) ej2d

ej2d :
gcc $(CFLAGS) -o $(TARGET) $(SRC) $(LDFLAGS)

// gcc需要以tab开头

clean :
-rm -f ej2d.exe
-rm -f ej2d

.PHONY : all clean 

CFLAGS = -g -Wall 
LDFLAGS = -lpthread -llua -lm

uname_S := $(shell sh -c 'uname -s 2>/dev/null || echo not')
ifeq ($(uname_S), Darwin)
	SHARED = -fPIC -dynamiclib -Wl,-undefined,dynamic_lookup
// -fPIC 生成的地址改为相对地址,生成共享库时需要指定为相对地址
// -dynamiclib darwin系统中生成动态链接库参数
// -Wl,option 将option当做一个参数传给linker
else
	LDFLAGS += -lrt -Wl,-E
	SHARED = -fPIC --shared
endif

ifneq ($(uname_S), FreeBSD)
	LDFLAGS += -ldl
endif

all : \
  skynet \
  service/snlua.so \
  service/logger.so \
  service/gate.so \
  service/client.so \
  service/master.so \
  service/multicast.so \
  service/tunnel.so \
  service/harbor.so \
  service/localcast.so \
  luaclib/skynet.so \
  luaclib/socketdriver.so \
  luaclib/int64.so \
  luaclib/mcast.so \
  luaclib/bson.so \
  luaclib/mongo.so \
  client

skynet : \
  skynet-src/skynet_main.c \
  skynet-src/skynet_handle.c \
  skynet-src/skynet_module.c \
  skynet-src/skynet_mq.c \
  skynet-src/skynet_server.c \
  skynet-src/skynet_start.c \
  skynet-src/skynet_timer.c \
  skynet-src/skynet_error.c \
  skynet-src/skynet_harbor.c \
  skynet-src/skynet_multicast.c \
  skynet-src/skynet_group.c \
  skynet-src/skynet_env.c \
  skynet-src/skynet_monitor.c \
  skynet-src/skynet_socket.c \
  skynet-src/socket_server.c \
  luacompat/compat52.c
	gcc $(CFLAGS) -Iluacompat -o $@ $^ -Iskynet-src $(LDFLAGS)

luaclib:
	mkdir luaclib

service/tunnel.so : service-src/service_tunnel.c
	gcc $(CFLAGS) $(SHARED) $^ -o $@ -Iskynet-src

service/multicast.so : service-src/service_multicast.c
	gcc $(CFLAGS) $(SHARED) $^ -o $@ -Iskynet-src

service/master.so : service-src/service_master.c
	gcc $(CFLAGS) $(SHARED) $^ -o $@ -Iskynet-src

service/harbor.so : service-src/service_harbor.c
	gcc $(CFLAGS) $(SHARED) $^ -o $@ -Iskynet-src

service/logger.so : skynet-src/skynet_logger.c
	gcc $(CFLAGS) $(SHARED) $^ -o $@ -Iskynet-src

service/snlua.so : service-src/service_lua.c service-src/luacode_cache.c service-src/luaalloc.c
	gcc $(CFLAGS) $(SHARED) -Iluacompat $^ -o $@ -Iskynet-src

service/gate.so : service-src/service_gate.c
	gcc $(CFLAGS) $(SHARED) $^ -o $@ -Iskynet-src

service/localcast.so : service-src/service_localcast.c
	gcc $(CFLAGS) $(SHARED) $^ -o $@ -Iskynet-src

luaclib/skynet.so : lualib-src/lua-skynet.c lualib-src/lua-seri.c lualib-src/trace_service.c lualib-src/timingqueue.c | luaclib
	gcc $(CFLAGS) $(SHARED) -Iluacompat $^ -o $@ -Iskynet-src -Iservice-src -Ilualib-src

service/client.so : service-src/service_client.c
	gcc $(CFLAGS) $(SHARED) $^ -o $@ -Iskynet-src

luaclib/socketdriver.so : lualib-src/lua-socket.c | luaclib
	gcc $(CFLAGS) $(SHARED) -Iluacompat $^ -o $@ -Iskynet-src -Iservice-src

luaclib/int64.so : lua-int64/int64.c | luaclib
	gcc $(CFLAGS) $(SHARED) -Iluacompat -O2 $^ -o $@ 

luaclib/mcast.so : lualib-src/lua-localcast.c | luaclib
	gcc $(CFLAGS) $(SHARED) -Iluacompat $^ -o $@ -Iskynet-src -Iservice-src

luaclib/bson.so : lualib-src/lua-bson.c | luaclib
	gcc $(CFLAGS) $(SHARED) -Iluacompat $^ -o $@ 

luaclib/mongo.so : lualib-src/lua-mongo.c | luaclib
	gcc $(CFLAGS) $(SHARED) -Iluacompat $^ -o $@ 

client : client-src/client.c
	gcc $(CFLAGS) $^ -o $@ -lpthread

clean :
	rm skynet client service/*.so luaclib/*.so

找到一个编辑json表格ajax grid控件

http://www.jqwidgets.com/

策划还是比较喜欢原来的类似表格来编辑,不喜欢直接编辑json格式。

在网上找到了jqwidgets,里面的grid控件正好满足需求。

<script type="text/javascript">
        $(document).ready(function () {
        	var url='<c:url value='/gm/Gm/readParameter?id=${parameter.id}'/>';
            var source =
            {
                datatype: "json",
                datafields: [
                    { name: 'id', type: 'int' },
                    { name: 'name', type: 'string' },
                    { name: 'gmLoginUrl', type: 'string' },
                    { name: 'ip', type: 'string' },
                    { name: 'port', type: 'int' },
                    { name: 'status', type: 'int' },
                    { name: 'recommend', type: 'bool' }
                ],
                id: 'id',
                url: url
            };
            var dataAdapter = new $.jqx.dataAdapter(source);
            $("#jqxgrid").jqxGrid(
            {
                width: 1200,
                source: dataAdapter,
                columnsresize: true,
                editable: true,
                columns: [
                  { text: 'id', datafield: 'id', width: 50 },
                  { text: 'name', datafield: 'name', width: 150 },
                  { text: 'ip', datafield: 'ip', width: 120 },
                  { text: 'port', datafield: 'port', minwidth: 120 },
                  { text: '状态', datafield: 'status', minwidth: 50 },
                  { text: '推荐', datafield: 'recommend', maxwidth: 50,columntype: 'checkbox' },
                  { text: '后台连接', datafield: 'gmLoginUrl', width: 280 }
                ]
            });
            $("#jsonExport").jqxButton({});
            $("#jsonExport").click(function () {
                var gridContent=$("#jqxgrid").jqxGrid('exportdata', 'json');
                $("#editParameterForm_json").val(gridContent);
                $("#editParameterForm").submit();
            });
        });</script>

在使用grid导出json时,数字被3个一组分组了,12345被格式化为 12,345 生成后面一堆错误。

最终未找到的完美的解决方式,只好设置这一列为字符串,避免被分组。

 

java上的协程

最近几天,有时间查看了一下java的中协程。

在java中大大小小的协程框架竟然有20多个,-.-!

总的来说java本身不支持协程,因此需要在vm级别进行修改才可以支持协程。

vm修改,分为两种,一种是直接修改生成的class bytecode如kilim之类。

另一类是直接运行在vm上的语言级别的支持,比如:akka。

kilim和akka也是目前公认的性能最好的框架。

我先测试了一下kilim,确实非常不错。多线程完全避免了线程切换和内存锁,而且使用url和sleep也不会阻塞线程运行。

我的电脑是8核cpu,在kilim中使用sleep,达到8个时会被线程阻塞。查找下解决方案。

我在kilim中使用的是Thread.sleep,如果改为使用kilim自带的sleep,则不会阻塞线程。

基本上搞明白了,kilim只是将线程改为了协程,避免了线程的上下文切换,但如果计算会阻塞,依旧会阻塞kilim,看来,httpclient及数据库操作和io需要改为non-blocking,才可以发挥kilim的全部性能。

kilim中还需要解决同步访问数据库、操作文件等问题,这些都必须改为non-blocking。

接着尝试下将server改为kilim,比较下性能。