一、认识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. Linux 新手常用命令

    ubuntu的root用户默认是禁止的,需要手动打开才行 事实上ubuntu下的所有操作都用不到root用户,由于sudo的合理使用,避免了root用户下误操作而产生的毁灭性问题 root账号启用方法 ...

  2. MVC Model Binder 规则

    http://www.cnblogs.com/mszhangxuefei/archive/2012/05/15/mvcnotes_30.html 使用默认的Model Binder(Using the ...

  3. [LeetCode] Decode Ways 解题思路

    A message containing letters from A-Z is being encoded to numbers using the following mapping: 'A' - ...

  4. php 生成正态分布随机数

    这个函数比较冷门,连官方文档都不太齐全 function stats_rand_gen_normal(av, sd);   //av是平均值,sd是标准偏差 使用这个函数需要,安装pecl stats ...

  5. opencv学习笔记-图像对比度、亮度调节

    在数学中我们学过线性理论,在图像亮度和对比度调节中同样适用,看下面这个公式: 在图像像素中其中: 参数f(x)表示源图像像素. 参数g(x) 表示输出图像像素. 参数a(需要满足a>0)被称为增 ...

  6. PAT 1080. Graduate Admission (30)

    It is said that in 2013, there were about 100 graduate schools ready to proceed over 40,000 applicat ...

  7. 加速 Gradle 构建大型 Android 项目的方法[转]

    加速 Gradle 构建大型 Android 项目的方法 时间 2016-03-14 20:38:00  Mystra 原文  http://www.wangchenlong.org/2016/03/ ...

  8. 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 ...

  9. linux内存管理系列 +CFS 图解

    http://blog.chinaunix.net/uid-20543183-id-1930786.html http://blog.csdn.net/ustc_dylan/article/categ ...

  10. Motion——shake攻略

    1.子类化窗口 如果响应链中没有motionEnded:withEvent:消息的接收者,那么该消息就会被发送给应用程序的window对象.所以需要在window对象上拦截motionEnded:wi ...