以python语言里的marshal为例, 基本序列化方式为: 类型说明+真实数据
这种方法简单,处理起来方便,因此为多种语言的机制使用。但是当极端情况出现时,事情变得不那么顺利, 比如曾经遇到过很大的字典,字典有许多k,v 对,值又是一个有很多元素的字典或者数组,这样虽然每个元素不大,但是总和起来序列化后是比较大的数据。由于python语言GIL的限制,loads大数据的时候,其他的线程就会被阻塞(不是严格意义上的阻塞,因为还是能被调用的,但是机会非常少),系统会变得反应慢。
通常遇到比较大的数据的反应是将数据分割成足够小的数据块的组合,数据块之间可以有间歇的休息时间,这样其他的线程就可以得到充足的处理时间,哪怕付出的代价是大数据块的时间稍微多一点。而传统的类型+数据模式是不方便分割数据,尤其当数据中有字典和列表。
我所想到的解决方案是采用一种新的序列化方法: 栈式序列化方法。比如一个字典
可以将伊序列化为 ["a", 3, "b", "c", 4, "d", 5, (DICT, 2), (DICT, 2)]
反序列化的过程, 则可以非形式化地表达为
这种模式类似于栈式语言, 了解java虚拟机的哥们也熟悉。
带来的优点是, 可以以任意长度截断成数据包,传送到处理器, 而处理器只要按顺序等待一个一个的数据包,来一个可以处理一个。比如 以上数据分成三个包发送
["a", 3, "b", "c"], [ 4, "d", 5], [(DICT, 2), (DICT, 2)]
>>> import marshal
>>> marshal.dumps(4.5)
'g\x00\x00\x00\x00\x00\x00\x12@'
>>> marshal.dumps(3)
'i\x03\x00\x00\x00'
>>> marshal.dumps('astring')
't\x07\x00\x00\x00astring'
>>> marshal.dumps({'a': 3})
'{t\x01\x00\x00\x00ai\x03\x00\x00\x000'
这种方法简单,处理起来方便,因此为多种语言的机制使用。但是当极端情况出现时,事情变得不那么顺利, 比如曾经遇到过很大的字典,字典有许多k,v 对,值又是一个有很多元素的字典或者数组,这样虽然每个元素不大,但是总和起来序列化后是比较大的数据。由于python语言GIL的限制,loads大数据的时候,其他的线程就会被阻塞(不是严格意义上的阻塞,因为还是能被调用的,但是机会非常少),系统会变得反应慢。
通常遇到比较大的数据的反应是将数据分割成足够小的数据块的组合,数据块之间可以有间歇的休息时间,这样其他的线程就可以得到充足的处理时间,哪怕付出的代价是大数据块的时间稍微多一点。而传统的类型+数据模式是不方便分割数据,尤其当数据中有字典和列表。
我所想到的解决方案是采用一种新的序列化方法: 栈式序列化方法。比如一个字典
{"a": 3, "b": {"c": 4, "d": 5}}
可以将伊序列化为 ["a", 3, "b", "c", 4, "d", 5, (DICT, 2), (DICT, 2)]
反序列化的过程, 则可以非形式化地表达为
stack = []
for elem in serialized:
if elem is basic element such as string, int, number, ...
push elem into stack
elif elem is (DICT, num) # command
pop num * 2 elements from stack make them as a dict
push the dict into stack
else .....
这种模式类似于栈式语言, 了解java虚拟机的哥们也熟悉。
带来的优点是, 可以以任意长度截断成数据包,传送到处理器, 而处理器只要按顺序等待一个一个的数据包,来一个可以处理一个。比如 以上数据分成三个包发送
["a", 3, "b", "c"], [ 4, "d", 5], [(DICT, 2), (DICT, 2)]