开发可正确序列化和反序列化的guava table组件

首先,什么是Table,可以理解为前端使用的html table组件,它具有行头,列头,以及具体的数据.即描述有多少行,多少列,在行为X,列为Y的二维格子中所对应的值是多少.

在使用google guava组件同时,也在讨论其组件的一些局限性,比如它的不变性,对序列化支持的不友好等.
其中table就是一个例子,作为一个表格组件的后端对应数据结构,其自带的table实现完全不能满足实际的需要.其大部分实现都是不可变的,即意味着必须要使用类似builder的模式来进行创建,一旦创建好之后,就不能再次修改.那么,作为一个实际可用的table实现,它需要哪些特性呢.以下例出我们所需要的要求:

1. 查找 按行,按列,快速定位
2. 快速迭代,按行,按列,支持稀疏迭代
3. 泛型支持(通用化)
4. 支持排序
5. 行,列动态增长,削减
6. 反序列化支持(json)

也就是说,我们期望像使用java的集合一样,创建出相应的数据之后,一直都是可变的,并且可以随意地进行传递,然后再任意地进行处理.无论按行,按列,都能够很好地使用.
本篇即描述了如何实现这样一个table组件,以及它最终的效果.

已实现的github地址:https://github.com/flym/array-tree-table

继续阅读“开发可正确序列化和反序列化的guava table组件”

alibaba fastjson(json序列化器)序列化部分源码解析-2-性能优化A

    上篇地址:http://www.iflym.com/index.php/code/alibaba-fastjson-json-serializer-chapter-source-analyse-one-global-analyse.html
    接上篇,在论述完基本概念和总体思路之后,我们来到整个程序最重要的部分-性能优化。之所以会有fastjson这个项目,主要问题是为了解决性能这一块的问题,将序列化工作提高到一个新的高度。我们提到,性能优化主要有两个方面,一个如何将处理后的数据追加到数据储存器,即outWriter中;二是如何保证处理过程中的速度。
    本篇从第一个性能优化方面来进行解析,主要的工作集中在类SerializeWriter上。

    首先,类的声明,继承了Writer类,实现了输出字符的基本功能,并且提供了拼接数据的基本功能。内部使用了一个buf数组和count来进行计数。这个类的实现结果和StringBuilder的工作模式差不多。但我们说为什么不使用StringBuilder,主要是因为StringBuilder没有针对json序列化提出更加有效率的处理方式,而且单就StringBuilder而言,内部是为了实现字符串拼接而生,因为很自然地使用了更加能够读懂的方式进行处理。相比,serializeWriter单处理json序列化数据传输,功能单一,因此在某些方面更加优化一些。
    在类声明中,这里有一个优化措施(笔者最开始未注意到,经作者指出之后才明白)。即是对buf数组的缓存使用,即在一次处理完毕之后,储存的数据容器并不销毁,而是留在当前线程变量中。以便于在当前线程中再次序列化json时使用。源码如下:

public SerializeWriter(){
        buf = bufLocal.get(); // new char[1024];
        if (buf == null) {
            buf = new char[1024];
        } else {
            bufLocal.set(null);
        }
    }

    在初始构造时,会从当前线程变量中取buf数组并设置在对象属性buf中。而在每次序列化完成之后,会通过close方法,将此buf数组再次绑定在线程变量当中,如下所示:

/**
     * Close the stream. This method does not release the buffer, since its contents might still be required. Note:
     * Invoking this method in this class will have no effect.
     */
    public void close() {
        bufLocal.set(buf);
    }

    当然,buf重新绑定了,肯定计数器count应该置0。这是自然,count是对象属性,每次在新建时,自然会置0。

    在实现过程当中,很多具体的实现是借鉴了StringBuilder的处理模式的,在以下的分析中会说到。

    总体分类
   
    接上篇而言,我们说outWriter主要实现了五个方面的输出内容。
        1,提供writer的基本功能,输出字符,输出字符串
        2,提供对整形和长整形输出的特殊处理
        3,提供对基本类型数组输出的支持
        4,提供对整形+字符的输出支持
        5,提供对字符串+双(单)引号的输出方式
    五个方面主要体现在不同的作用域。第一个提供了最基本的writer功能,以及在输出字符上最基本的功能,即拼接字符数组(不是字符串);第二个针对最常用的数字进行处理;第三个,针对基本类型数组类处理;第四个针对在处理集合/数组时,最后一位的特殊处理,联合了输出数字和字符的双重功能,效率上比两个功能的实现原理上更快一些;第四个,针对字符串的特殊处理(主要是特殊字符处理)以及在json中,字符串的引号处理(即在json中,字符串必须以引号引起来)。

    实现思想

    数据输出最后都变成了拼接字符的功能,即将各种类型的数据转化为字符数组的形式,然后将字符数组拼接到buf数组当中。这中间主要逻辑如下:
        1    对象转化为字符数组
        2    准备装载空间,以容纳数据
        2.1    计数器增加
        2.2    扩容,字符数组扩容
        3    装载数据
        4    计数器计数最新的容量,完成处理
    这里面主要涉及到一个buf数组扩容的概念,其使用的扩容函数expandCapacity其内部实现和StringBuilder中一样。即(当前容量 + 1)* 2,具体可以见相应函数或StringBuilder.ensureCapacityImpl函数。

继续阅读“alibaba fastjson(json序列化器)序列化部分源码解析-2-性能优化A”

alibaba fastjson(json序列化器)序列化部分源码解析-1-总体分析

    fastjson官方地址: http://code.alibabatech.com/wiki/display/FastJSON/Home
    从javaeye上看到了阿里一位人士写的fastjson,特别是其中如何将java对象序列化成json字符串这段。笔者比较关注,因为在笔者的项目中就用了一个json序列化器(造的轮子)。就下载下来看了一看,先不说和笔者所用的轮子有何区别,单就用了一个简单的测试器,来测试一下两者的处理速度。测试代码就不贴了,简单地说下测试结果。在jvm充分优化的情况下(for循环执行了很多次之后),笔者所使用的java序列化器处理速度不是很均匀,在结尾有短暂的变化(可能与虚拟机回收有关系);而fastjson在后面的处理过程当中,一般很均匀(后来发现与使用的buf分配方式有关)。最主要的区别莫在于,fastjson的速度那是不能对比了。
    经过分析源码之后,发现fastjson在处理json优化上面还是下了很大的工夫的。笔者准备从以下几个方面对fastjson作一个简单的解析,也让使用fastjson的同学对fastjson有一个简单的认识。
        1    总体分析    分析json序列化的总体思路和解析过程
        2    性能分析A  针对字符生产部分(即outWriter)对不同类型数据的处理和与性能相关处理部分
        3    性别分析B  针对序列化过程部分(即objectSerializer)对不同类型的序列化过程处理和与性能相关处理部分
        4    对象解析分析    对javaBean解析部分和针对字段输出部分的处理和解析
    源码分析基于1.0.5版本。

    总体分析,首先上图,即fastjson的总体处理思想,其实也是所有json序列化器需要考虑的问题。
    在这里,需要考虑的主要有两个部分,一是临时保存在序列化过程中用于储存数据的容器,二是处理对象序列化的序列化器。
    在fastjson中,保存数据的容器使用了wirter,字符输出流,而且是自实现的一个字符输出流。相对原来的writer,追加了很多需要输出的信息的实现,比如输出一个字符串,输出一个字符,输出一个long类型数据等。而处理对象序列化的序列化器,而使用了责任链模式和工厂模式,将不同类型的java对象分散到不同的序列化器当中。而每个序列化器只处理与自身类型相对应的数据信息,这样就避免了在处理时,各种情况交织在一块,逻辑混乱的问题。
    下面就源码本身作一个分析,其中结合两个部分进行分析。

继续阅读“alibaba fastjson(json序列化器)序列化部分源码解析-1-总体分析”