学习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 ...
随机推荐
- Linux 新手常用命令
ubuntu的root用户默认是禁止的,需要手动打开才行 事实上ubuntu下的所有操作都用不到root用户,由于sudo的合理使用,避免了root用户下误操作而产生的毁灭性问题 root账号启用方法 ...
- MVC Model Binder 规则
http://www.cnblogs.com/mszhangxuefei/archive/2012/05/15/mvcnotes_30.html 使用默认的Model Binder(Using the ...
- [LeetCode] Decode Ways 解题思路
A message containing letters from A-Z is being encoded to numbers using the following mapping: 'A' - ...
- php 生成正态分布随机数
这个函数比较冷门,连官方文档都不太齐全 function stats_rand_gen_normal(av, sd); //av是平均值,sd是标准偏差 使用这个函数需要,安装pecl stats ...
- opencv学习笔记-图像对比度、亮度调节
在数学中我们学过线性理论,在图像亮度和对比度调节中同样适用,看下面这个公式: 在图像像素中其中: 参数f(x)表示源图像像素. 参数g(x) 表示输出图像像素. 参数a(需要满足a>0)被称为增 ...
- PAT 1080. Graduate Admission (30)
It is said that in 2013, there were about 100 graduate schools ready to proceed over 40,000 applicat ...
- 加速 Gradle 构建大型 Android 项目的方法[转]
加速 Gradle 构建大型 Android 项目的方法 时间 2016-03-14 20:38:00 Mystra 原文 http://www.wangchenlong.org/2016/03/ ...
- LeetCode153:Find Minimum in Rotated Sorted Array
Suppose a sorted array is rotated at some pivot unknown to you beforehand. (i.e., 0 1 2 4 5 6 7 migh ...
- linux内存管理系列 +CFS 图解
http://blog.chinaunix.net/uid-20543183-id-1930786.html http://blog.csdn.net/ustc_dylan/article/categ ...
- Motion——shake攻略
1.子类化窗口 如果响应链中没有motionEnded:withEvent:消息的接收者,那么该消息就会被发送给应用程序的window对象.所以需要在window对象上拦截motionEnded:wi ...