学习protobuf
一、认识Protobuf
ref:http://blog.csdn.net/program_think/article/details/4229773
摘要:
1. protobuf是一个开源项目。
2. 用于把某种数据结构的信息,以某种格式保存起来。主要用于数据存储、传输协议格式。
3. 优点:◇性能好/效率高◇代码生成机制◇支持“向后兼容”和“向前兼容”◇支持多种编程语言
4. 缺点:◇应用不够广◇二进制格式导致可读性差,定位问题难◇缺乏自描述
使用它的最大理由应该是“代码生成”,也就是只要写好描述脚本,它可以自动生成c++,java,或其他语言的类,自带序列化和反序列化功能,极大的方便了开发者,不再需要手动写数据存储类。另外就是序列化的密度和压缩比大;以及不同语言的序列化结果一致,使得不同语言可一致处理。
二、安装Python Protobuf
1. pip install protobuf
这将安装python对protobuf的支持库,正常情况下可能只是安装pure python的支持,效率不如c扩展。为了安装c扩展,需要执行:
PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=cpp \
pip install protobuf
会编译安装c扩展,如果有编译错误,需要解决。
2. 安装protobuf 代码生成器 -- protoc
在官网(http://code.google.com/p/protobuf/)下载安装包或源代码包,直接安装或者编译(按readme提示)安装。
三、示例
建立addressbook.proto文件:
package tutorial;
message Person {
required string name = 1;
required int32 id = 2;
optional string email = 3;
enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message PhoneNumber {
required string number = 1;
optional PhoneType type = 2 [default = HOME];
}
repeated PhoneNumber phone = 4;
}
message AddressBook {
repeated Person person = 1;
}
执行命令:
/usr/local/bin/protoc -I=./ --python_out=./ ./addressbook.proto
将在同目录下生成addressbook_pb2.py文件,建立protobuf_test.py文件:
def testProto():
import addressbook_pb2
person = addressbook_pb2.Person()
person.id = 1234
person.name = "John Doe"
person.email = "jdoe@example.com"
phone = person.phone.add()
phone.number = "555-4321"
phone.type = addressbook_pb2.Person.HOME
print 'src:', person
str = person.SerializeToString()
person2 = addressbook_pb2.Person()
person2.ParseFromString(str)
print 'Serialize len:%d' % (len(str))
print 'dst:',person2
if __name__ == '__main__':
testProto()
运行,显示如下:
src: name: "John Doe"
id: 1234
email: "jdoe@example.com"
phone {
number: "555-4321"
type: HOME
}
Serialize len:45
dst: name: "John Doe"
id: 1234
email: "jdoe@example.com"
phone {
number: "555-4321"
type: HOME
}
可见序列化和反序列化成功。
四、提高
ref:http://yz.mit.edu/wp/fast-native-c-protocol-buffers-from-python/
摘要:
1.写了一段python测试protobuf序列化和反序列化的时间消耗。
2.使用c扩展和纯python库执行的性能对比,序列化15倍,反序列化8倍。
3.使用protoc直接生成proto的c++代码,封装c++代码生成c扩展,安装c扩展。在测试代码中import这个c扩展,执行测试代码将自动使用c扩展版本进行数据存储和处理,性能将得到进一步提高,相比纯python库,序列化68倍,反序列化13倍。
例:
/usr/local/bin/protoc -I=./ --cpp_out=./ ./addressbook.proto
将生成addressboo.pb.h和addressboo.pb.cc文件。
建立addressbook.c文件:
#include <Python.h>
static PyMethodDef podMethods[] = {
{NULL, NULL, 0, NULL} /* Sentinel */
};
PyMODINIT_FUNC
initpodpb(void)
{
PyObject *m;
m = Py_InitModule("podpb", podMethods);
if (m == NULL)
return;
}
建立setup.py文件:
import os
import platform
from setuptools import setup, find_packages
from distutils.core import setup, Extension
setup(
ext_modules=[Extension('podpb',
sources=['./addressbook.c','./addressbook.pb.cc'], libraries=['protobuf'])]
)
执行python setup.py build命令,有以下输出:
g++ -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions build/temp.linux-x86_64-2.6/./addressbook.o build/temp.linux-x86_64-2.6/./addressbook.pb.o -lprotobuf -o build/lib.linux-x86_64-2.6/podpb.so
表示生成了对应的c扩展podpb.so,将这个so文件复制到当前目录下。
在protobuf_test.py加入测试代码:
import os, random
import timeit
#import podpb
def ser(xs):
return [x.SerializeToString() for x in xs]
def parse(ys):
import addressbook_pb2
for y in ys: addressbook_pb2.Person().ParseFromString(y)
def benchTest():
import addressbook_pb2
nruns = 1000
nwarmups = 100
xs = [] # your protobufs
for i in range(10):
rId = random.randint(100000, 999999)
person = addressbook_pb2.Person()
person.id = rId
person.name = "John Doe"
person.email = "jdoe@example.com"
phone = person.phone.add()
phone.number = "555-4321"
phone.type = addressbook_pb2.Person.HOME
xs.append(person)
t = timeit.Timer(lambda:None)
t.timeit(nwarmups)
print 'noop:', t.timeit(nruns) / nruns
t = timeit.Timer(lambda: ser(xs))
t.timeit(nwarmups)
print 'ser:', t.timeit(nruns) / nruns / len(xs)
ys = ser(xs)
t = timeit.Timer(lambda: parse(ys))
t.timeit(nwarmups)
print 'parse:', t.timeit(nruns) / nruns / len(xs)
print 'msg size:', sum(len(y) for y in ys) / len(ys)
if __name__ == '__main__':
testProto()
benchTest()
未使用podpb及PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION,有:
noop: 9.29832458496e-08
ser: 2.62283086777e-05
parse: 3.05251121521e-05
msg size: 46
使用PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION有:
noop: 9.08374786377e-08
ser: 2.59931087494e-06
parse: 7.11431503296e-06
msg size: 46
使用podpb及PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION有:
noop: 9.20295715332e-08
ser: 7.13109970093e-07
parse: 4.77969646454e-06
msg size: 46
和文章对比性能差别不那么大,但趋势是符合的。
学习protobuf的更多相关文章
- go语言学习--protobuf的学习
最近在学习中遇到了protobuf,哇喔竟然不知道,马上进行了学习,protobuf也是数据解析的方式,平时使用最多的是json和xml,那么好了,对比下他们的区别,并且附上protobuf的使用. ...
- 学习 protobuf(一)—— ubuntu 下 protobuf 2.6.1 的安装
下载地址:https://github.com/google/protobuf/releases/download/v2.6.1/protobuf-2.6.1.tar.gz(如果初次下载失败,不妨多试 ...
- 学习protobuf 感想
前俩篇博文是从大牛的博客抄过来的, 写的都很好. 这里还写简单写下自己的感想: 1. 和json比, protobuff编码后的体积小很多, 这是肯定的. 都源自于protobuff内部的一系列特殊的 ...
- Protocol Buffer学习教程之开篇概述(一)
1. Protocol Buffer是什么 Protocol Buffer是google旗下的产品,用于序列化与反序列化数据结构,但是比xml更小.更快.更简单,而且能跨语言.跨平台.你可以把你的数据 ...
- protobuf3的学习笔记
学习protobuf的过程中踩了不少的坑,这篇博文算是一个小结吧! 环境: windows VisualStudio Google.Protobuf.Tools. Google.Protobuf. 其 ...
- 【转】深入 ProtoBuf - 简介
之前在网络通信和通用数据交换等应用场景中经常使用的技术是 JSON 或 XML,而在最近的开发中接触到了 Google 的 ProtoBuf. 在查阅相关资料学习 ProtoBuf 以及研读其源码之后 ...
- Unity手游之路<三> 基于Unity+Java的聊天室源码
http://blog.csdn.net/janeky/article/details/17233199 项目介绍 这是一个简单的Unity项目,实现最基本的聊天室群聊功能.登录聊天室后,用户可以输入 ...
- .NET开源Protobuf-net组件修炼手册
一.前言 Protocol Buffer(简称Protobuf或PB) 是一个跨平台的消息交互协议,类似xml.json等 :别只会用Json和XML了,快来看看Google出品的Protocol B ...
- .NET开源Protobuf-net组件葵花手册
一.前言 我们都知道 protobuf是由Google开发的一款与平台无关,语言无关,可扩展的序列化结构数据格式,可用做数据存储格式, 通信协议 ! 在前面<.NET开源Protobuf-net ...
随机推荐
- HDOJ/HDU 1241 Oil Deposits(经典DFS)
Problem Description The GeoSurvComp geologic survey company is responsible for detecting underground ...
- Bzoj 2789: [Poi2012]Letters 树状数组,逆序对
2789: [Poi2012]Letters Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 278 Solved: 185[Submit][Stat ...
- PHP两个字符串比较(人为出错),两字符串类型和数据表面相等,但strcmp()结果不为0
PHP中,比较两个字符串是否相等用:strcmp(): PHP strcmp() 函数 PHP String 函数 定义和用法 strcmp() 函数比较两个字符串. 该函数返回: 0 - 如果两个字 ...
- 神经网络中误差反向传播(back propagation)算法的工作原理
注意:版权所有,转载需注明出处. 神经网络,从大学时候就知道,后面上课的时候老师也讲过,但是感觉从来没有真正掌握,总是似是而非,比较模糊,好像懂,其实并不懂. 在开始推导之前,需要先做一些准备工作,推 ...
- 小物件之radio单选列表
有时候在控制器中做了一个数组 然后需要在模板view中循环 同时还需要判断是否有选中的值,就会造成很多开始闭合标签 以前都是这样写 这样实在太繁琐了,不如封装一个小物件 封装函数如下: 代码如下: f ...
- 写一段方便的SQL 循环查每一天的数据
declare @recd int,@i int,@a int,@count int,@day1 date,@day2 date,@days int set @day1='2014-8-24' set ...
- 【Android - 基础】之PopupWindow的使用
创建一个类继承自PopupWindow,编写自定义的PopupWindow类.示例代码如下: import android.app.Activity; import android.graphics. ...
- JSTL 数字日期标签库
<frm:formatNumber/>标签 该标签依据特定的区域将数字改变为不同的格式来显示. 被格式化的数据<frm:formatNumber> <fmt:format ...
- Bootstrap-基于jquery的bootstrap在线文本编辑器插件Summernote
Summernote是一个基于jquery的bootstrap超级简单WYSIWYG在线编辑器.Summernote非常的轻量级,大小只有30KB,支持Safari,Chrome,Firefox.Op ...
- XRDP与VNC的关系
如果仅仅安装XRDP协议.是不能在windows上使用远程桌面连接到Ubuntu. 还须要安装VNCServer才行. 所以,XRDP启动之后.系统会自己主动启动一个VNC会话进程监听服务. 当我们通 ...