一、认识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的更多相关文章

  1. go语言学习--protobuf的学习

    最近在学习中遇到了protobuf,哇喔竟然不知道,马上进行了学习,protobuf也是数据解析的方式,平时使用最多的是json和xml,那么好了,对比下他们的区别,并且附上protobuf的使用. ...

  2. 学习 protobuf(一)—— ubuntu 下 protobuf 2.6.1 的安装

    下载地址:https://github.com/google/protobuf/releases/download/v2.6.1/protobuf-2.6.1.tar.gz(如果初次下载失败,不妨多试 ...

  3. 学习protobuf 感想

    前俩篇博文是从大牛的博客抄过来的, 写的都很好. 这里还写简单写下自己的感想: 1. 和json比, protobuff编码后的体积小很多, 这是肯定的. 都源自于protobuff内部的一系列特殊的 ...

  4. Protocol Buffer学习教程之开篇概述(一)

    1. Protocol Buffer是什么 Protocol Buffer是google旗下的产品,用于序列化与反序列化数据结构,但是比xml更小.更快.更简单,而且能跨语言.跨平台.你可以把你的数据 ...

  5. protobuf3的学习笔记

    学习protobuf的过程中踩了不少的坑,这篇博文算是一个小结吧! 环境: windows VisualStudio Google.Protobuf.Tools. Google.Protobuf. 其 ...

  6. 【转】深入 ProtoBuf - 简介

    之前在网络通信和通用数据交换等应用场景中经常使用的技术是 JSON 或 XML,而在最近的开发中接触到了 Google 的 ProtoBuf. 在查阅相关资料学习 ProtoBuf 以及研读其源码之后 ...

  7. Unity手游之路<三> 基于Unity+Java的聊天室源码

    http://blog.csdn.net/janeky/article/details/17233199 项目介绍 这是一个简单的Unity项目,实现最基本的聊天室群聊功能.登录聊天室后,用户可以输入 ...

  8. .NET开源Protobuf-net组件修炼手册

    一.前言 Protocol Buffer(简称Protobuf或PB) 是一个跨平台的消息交互协议,类似xml.json等 :别只会用Json和XML了,快来看看Google出品的Protocol B ...

  9. .NET开源Protobuf-net组件葵花手册

    一.前言 我们都知道 protobuf是由Google开发的一款与平台无关,语言无关,可扩展的序列化结构数据格式,可用做数据存储格式, 通信协议 ! 在前面<.NET开源Protobuf-net ...

随机推荐

  1. 《C语言程序设计现代方法》第3章 格式化输入/输出

    完整的细节将留到第22章中介绍. 调用printf函数一次可以打印的值的个数没有限制. 注意:C语言编译器不会检查格式串中转换说明的数量是否和输出项的数量相互匹配,也不会检查转换说明是否适合要显示项的 ...

  2. Bzoj 2393: Cirno的完美算数教室 容斥原理,深搜

    2393: Cirno的完美算数教室 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 287  Solved: 175[Submit][Status][ ...

  3. 一步一步写一个简单通用的makefile(三)

    上一篇一步一步写一个简单通用的makefile(二) 里面的makefile 实现对通用的代码进行编译,这一章我将会对上一次的makefile 进行进一步的优化. 优化后的makefile: #Hel ...

  4. Python运行机制

    闲来无事,简单画了一下Python的运行机制,纯属娱乐:

  5. 如何使用chown?

    以test为例,目前test归root用户拥有,也归root组拥有 [root@localhost home]# ls -al total 36 drwxr-xr-x    6 root     ro ...

  6. 【转】谁说Vim不是IDE?(一)

    谁说Vim不是IDE?(一)   话说操作系统.编程语言和编辑器似乎是程序员永恒的吐槽话题,技术发展了几十年,大家讨论起这几个“之争”还是充满愤怒.津津乐道.有人描述过Emacs和VI程序员,大家沿着 ...

  7. nyoj 353 3D dungeon

    3D dungeon 时间限制:1000 ms  |  内存限制:65535 KB 难度:2   描述 You are trapped in a 3D dungeon and need to find ...

  8. Verilog HDL模块的结构

    一个设计是由一个个模块(module)构成的.一个模块的设计如下: 1.模块内容是嵌在module 和endmodule两个语句之间.每个模块实现特定的功能,模块可进行层次的嵌套,因此可以将大型的数字 ...

  9. pom.xml第一行报错

    错误:Cannot detect Web Project version. Please specify version of Web Project through <version> ...

  10. Java 线程第三版 第一章Thread导论、 第二章Thread的创建与管理读书笔记

    第一章 Thread导论 为何要用Thread ? 非堵塞I/O      I/O多路技术      轮询(polling)      信号 警告(Alarm)和定时器(Timer) 独立的任务(Ta ...