Javaの高性能高速コピー方法です.Cloneable?

3933 ワード

本人がデータベースキャッシュ層を設計する際には,データを深くコピーする必要があり,ユーザが操作するデータオブジェクトは共有されない.
この考え方は実際にErlangと似ており,データを共有しないで同時問題を解決することである.
 
1.シーケンス化?
元のやり方は、シーケンス化で、Jsonのシーケンス化、lib-jsonを使いました.どんなに伝統的な方法でも.データフィールドをjson保存にシーケンス化します.取り出すときは逆シーケンス化を行います.
100本のデータをテストして、100回の循環、意外にもTMの15秒を使いました.
これはどんな概念ですか.見るにたえないほど惨めだ.
そこでネット上で探して、Jacksonを探し当てて、性能のXXXと称して、Googleのgsonより高いXXX.
置換後、速度は3700 msに低下した.うん.そんなにおもしろい.
しかし、100回のフルクエリーで4秒近くかかり、受け入れられません.
コメント:
なぜ直接シーケンス化しないのですか?テーブル構造が変動するように設計したので,jsonのkey-valueを用いるとテーブル構造の拡張伸縮が容易である.
gsonという商品は、json文字列を一歩一歩オブジェクトに変換した.over-architectureすぎるとしか言えません.あまりにもapiがデザインされています.
jacksonはJsonNodeを使用していますが、本質はキー値が合っていて、このような適切な設計は、非常に便利です.
結論:
jsonを使うなら、json-libは糞で、まるで実験室の作品です.のジャックソンを使いましょう.
 
2.Cloneableインタフェース?
Javaが提供するオリジナルAPIの性能は、自分がどうやっても効率的であるという観点があります.
残念ながら、Cloneableインタフェースが1位で、public object cloneはありません.彼が何をしているのか分からない.継承インタフェースはpublicではありません.自分でobjectを呼び出す.clone. 2つ目は、オブジェクト配列がある場合か、ポインタ参照がある場合の浅いコピーです.
Usr_Equipment implements CLoneable
{
  @Override
  public Object clone() { super.clone();}}
残念ですが、このCloneableが何をしているのか本当に分かりません.
そこで自分でICloneable extends Cloneableインタフェースを設計し、cloneを暴露しました.
 
3.浅いコピーは深いコピーになりますか?
深いコピーを実現するには、オブジェクト全体に再帰的なプロパティを使用する必要があります.魔法全体の核心は、BeanCopierです.BeanMapよりも高性能!まずコードを放します.
package com.xtar.common.structure;

import java.lang.reflect.Array;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import net.sf.cglib.beans.BeanCopier;
import net.sf.cglib.core.Converter;

import com.xtar.common.interfaces.ICloneable;
import com.xtar.common.tool.ParserHelper;

public class CloneableBase implements ICloneable
{
	private static ConcurrentMap<Class<?>, BeanCopier> beanCopiers = new ConcurrentHashMap<Class<?>, BeanCopier>();

	@Override
	public Object clone()
	{
		try
		{
			Object clone = this.getClass().newInstance();

			BeanCopier copier = _createCopier(this.getClass());

			copier.copy(this, clone, new Converter()
			{
				@Override
				public Object convert(Object pojo, Class fieldType, Object fieldName)
				{
					return _clone(pojo);
				}
			});

			return clone;
		}
		catch (Exception e)
		{
			throw new RuntimeException(e);
		}
	}

	private static Object _clone(Object bean)
	{
		if (bean == null)
		{
			return null;
		}
		else if (bean instanceof ICloneable)
		{
			return ((ICloneable) bean).clone();
		}
		else
		{

					if (bean.getClass().isArray() && !bean.getClass().getComponentType().equals(byte.class))
					{
						int length = Array.getLength(bean);
						Object clone = Array.newInstance(bean.getClass().getComponentType(), length);
						for (int i = 0; i < length; i++)
						{
							Array.set(clone, i, _clone(Array.get(bean, i)));
						}
						return clone;
					}
					else
					{
						return bean;
					}
			}
		}
	}

	private static BeanCopier _createCopier(Class<?> clz)
	{
		if (beanCopiers.containsKey(clz))
			return beanCopiers.get(clz);
		beanCopiers.putIfAbsent(clz, BeanCopier.create(clz, clz, true));
		return beanCopiers.get(clz);

	}
}

上は深いコピー全体の魔法の核心です.
1)BeanCopierを使用し,このオブジェクトをキャッシュし,性能を50%向上させ,1 sから600 msに低下させた.
2)arrayを判断し,byte[]タイプであれば浅いコピーを直接使用する.これは特殊なオブジェクトです.
テストしてみると、BeanMapより2倍速いです.同じオブジェクトでは、BeanMapは1700 ms、BeanCopierは500 msしか必要ありません.
 
4.結論
私は、この方法はもう極致に達したと思っています.(バイナリシーケンス化はテストされていません).自分のオブジェクトがCloneableBaseを継承している限り、深度コピーを実現できます.