基于用户级线程的远程调用效率测试
2012-09-27 09:21
141 查看
将用户级线程添加到我的工具库中,主要的目的就是用于实现同步远程调用接口。这里的同步,是指在调用返回或超时之前,用户级线程的执行路径
阻塞在调用接口上,但其底层的线程并不会阻塞,可以继续其它的工作。
基于这个结构,我的服务器主线程将运行一个用户级线程调度器,并预先创建一组用户级线程池。当收从网络层收到一个网络消息时,从线程池中取出
一个空闲的线程,将消息交给它处理。这个线程在执行的过程中如果发生了阻塞调用,就将运行权交换给调度器,由调度器挑选下一个可用的线程执行。
阻塞线程直到超时,或被通知可以解除阻塞才被重新投入到调度器的可运行队列中。
下面贴出一个简单的测试代码,用于测试调用的效率。
首先是两个远程函数,一个用于求两数之和,一个用于求两数之积:
函数都很简单,将线程id,要求调用的函数名和参数打包并发送给服务器,然后调用coro_block阻塞在上面。当线程重新被唤醒时从应答包中读出返回值
并从函数返回.
下面是服务器对这两个远程调用的处理:
如代码所示,服务器将调用者的id,函数名和参数取出,执行所要求的计算,然后将计算结果发回给客户端.
下面再看下客户端的逻辑主循环:
主循环不断的尝试从网络层消息队列中获取应答包,接到应答包之后就对应的用户级线程唤醒,然后执行调度器。
在我的实验环境:一台i5 2.6GZ的双核笔记上,同时运行服务器和客户端,创建25W个用户级线程,平均每秒的远程调用次数大概在90W左右.
测试程序代码地址:https://github.com/sniperHW/kendylib/tree/master/rpctest
阻塞在调用接口上,但其底层的线程并不会阻塞,可以继续其它的工作。
基于这个结构,我的服务器主线程将运行一个用户级线程调度器,并预先创建一组用户级线程池。当收从网络层收到一个网络消息时,从线程池中取出
一个空闲的线程,将消息交给它处理。这个线程在执行的过程中如果发生了阻塞调用,就将运行权交换给调度器,由调度器挑选下一个可用的线程执行。
阻塞线程直到超时,或被通知可以解除阻塞才被重新投入到调度器的可运行队列中。
下面贴出一个简单的测试代码,用于测试调用的效率。
首先是两个远程函数,一个用于求两数之和,一个用于求两数之积:
static inline int sum(int32_t arg1,int32_t arg2) { coro_t co = get_current_coro(); wpacket_t wpk = wpacket_create(1,wpacket_allocator,64,0); wpacket_write_uint32(wpk,(int32_t)co); wpacket_write_string(wpk,"sum"); wpacket_write_uint32(wpk,arg1); wpacket_write_uint32(wpk,arg2); send_packet(g_channel,wpk); //send and block until the response from rpc server coro_block(co); int ret = rpacket_read_uint32(co->rpc_response); rpacket_destroy(&co->rpc_response); return ret; } static inline int product(int32_t arg1,int32_t arg2) { coro_t co = get_current_coro(); wpacket_t wpk = wpacket_create(1,NULL,64,0); wpacket_write_uint32(wpk,(int32_t)co); wpacket_write_string(wpk,"product"); wpacket_write_uint32(wpk,arg1); wpacket_write_uint32(wpk,arg2); send_packet(g_channel,wpk); //send and block until the response from rpc server coro_block(co); int ret = rpacket_read_uint32(co->rpc_response); rpacket_destroy(&co->rpc_response); return ret; }
函数都很简单,将线程id,要求调用的函数名和参数打包并发送给服务器,然后调用coro_block阻塞在上面。当线程重新被唤醒时从应答包中读出返回值
并从函数返回.
下面是服务器对这两个远程调用的处理:
void on_process_packet(struct connection *c,rpacket_t r) { uint32_t coro_id = rpacket_read_uint32(r); const char *function_name = rpacket_read_string(r); int32_t arg1 = rpacket_read_uint32(r); int32_t arg2 = rpacket_read_uint32(r); uint32_t i = 0; wpacket_t w = wpacket_create(0,wpacket_allocator,64,0); wpacket_write_uint32(w,coro_id); if(strcmp(function_name,"sum") == 0) wpacket_write_uint32(w,arg1+arg2); else wpacket_write_uint32(w,arg1*arg2); assert(w); connection_send(c,w,NULL); rpacket_destroy(&r); }
如代码所示,服务器将调用者的id,函数名和参数取出,执行所要求的计算,然后将计算结果发回给客户端.
下面再看下客户端的逻辑主循环:
void *logic_routine(void *arg) { uint32_t tick = GetSystemMs(); while(1) { rpacket_t rpk = peek_msg(g_channel,50); if(rpk) { coro_t co = (coro_t)rpacket_read_uint32(rpk); co->rpc_response = rpk; coro_wakeup(co); } uint32_t now = GetSystemMs(); if(now - tick > 1000) { printf("call_count:%u\n",call_count); tick = now; call_count = 0; } sche_schedule(g_sche); } }
主循环不断的尝试从网络层消息队列中获取应答包,接到应答包之后就对应的用户级线程唤醒,然后执行调度器。
在我的实验环境:一台i5 2.6GZ的双核笔记上,同时运行服务器和客户端,创建25W个用户级线程,平均每秒的远程调用次数大概在90W左右.
测试程序代码地址:https://github.com/sniperHW/kendylib/tree/master/rpctest
相关文章推荐
- 基于用户级线程的远程调用效率测试
- 基于XML-RPC的远程调用(Python,Java)
- 基于RMI实现远程调用的系统间通信
- 基于C++执行内存memcpy效率测试的分析
- 基于EJB3.0的远程方法调用
- Dnode:基于Node.js给浏览器提供异步远程方法调用
- 极限测试之Matlab与Forcal的递归函数调用效率
- Lua和C++之间调用效率测试
- Oracle11g 在虚拟机上安装数据库 在宿主机上安装SQLPLUS客户端 创建用户远程连接测试成功
- 基于Hessian的高性能远程对象调用的服务器端和客户端的Demo
- 基于WebService实现远程调用方式的系统间通信
- C语言中调用lua 脚本执行的效率测试
- Altova XMLSpy软件测试使用soap远程调用web服务
- C#/C++/CLI运行效率测试之一: C#通过CLR/C++调用Native CPP 类
- Lu基于系统内置对象创建扩展数据类型,小矩阵乘效率测试
- 基于条件测试实现角色调用
- 【Qt编程】基于Qt的词典开发系列<八>--用户登录及API调用的实现
- Dnode:基于Node.js给浏览器提供异步远程方法调用
- 基于Remoting的远程调用_服务器端实现
- 测试多个线程调用同一静态方法(无静态变量)时是否有线程安全问题