You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@ignite.apache.org by "Aleksey Plekhanov (Jira)" <ji...@apache.org> on 2020/07/03 07:45:00 UTC

[jira] [Updated] (IGNITE-13203) Improve OptimizedObjectOutputStream serialisation performance

     [ https://issues.apache.org/jira/browse/IGNITE-13203?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Aleksey Plekhanov updated IGNITE-13203:
---------------------------------------
    Fix Version/s:     (was: 2.9)

> Improve OptimizedObjectOutputStream serialisation performance
> -------------------------------------------------------------
>
>                 Key: IGNITE-13203
>                 URL: https://issues.apache.org/jira/browse/IGNITE-13203
>             Project: Ignite
>          Issue Type: Improvement
>          Components: binary
>    Affects Versions: 2.4, 2.5, 2.6, 2.7, 2.8, 2.7.5, 2.7.6, 2.8.1
>            Reporter: Manuel Núñez
>            Priority: Major
>
> 1. OptimizedObjectOutputStream -> writeObject0: Strings bigger than 4K reduce serialisation performance ~x2 respect JDK marshaller; proposal, use JDK marshaller for Strings bigger than 4K
> {code:java}
>  private void writeObject0(Object obj) throws IOException {
>         curObj = null;
>         curFields = null;
>         curPut = null;
>         if (obj == null)
>             writeByte(NULL);
>         else {
>         	boolean jdkStringWrite = false;
>         	// fix string bigger than 4K use JDK maschaller to improve performance
>         	if (obj instanceof String){
>         		jdkStringWrite = (((String)obj).length() > 4096);
>         	}
>             if ((jdkStringWrite || obj instanceof Throwable) && !(obj instanceof Externalizable) || U.isEnum(obj.getClass())) {
>                 // Avoid problems with differing Enum objects or Enum implementation class deadlocks.
>                 writeByte(JDK);
> ...
> {code}
> 2. OptimizedObjectOutputStream -> GridHandleTable: lookup performance can be improved  by caching hashes, especially for objects with high complexity and cycle references.
> {code:java}
> /*
>  * Licensed to the Apache Software Foundation (ASF) under one or more
>  * contributor license agreements.  See the NOTICE file distributed with
>  * this work for additional information regarding copyright ownership.
>  * The ASF licenses this file to You under the Apache License, Version 2.0
>  * (the "License"); you may not use this file except in compliance with
>  * the License.  You may obtain a copy of the License at
>  *
>  *      http://www.apache.org/licenses/LICENSE-2.0
>  *
>  * Unless required by applicable law or agreed to in writing, software
>  * distributed under the License is distributed on an "AS IS" BASIS,
>  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
>  * See the License for the specific language governing permissions and
>  * limitations under the License.
>  */
> package org.apache.ignite.internal.util;
> import java.util.Arrays;
> /**
>  * Lightweight identity hash table which maps objects to integer handles,
>  * assigned in ascending order.
>  *
>  */
> public class GridHandleTable {
>     /** Number of mappings in table/next available handle. */
>     private int size;
>     /** Size threshold determining when to expand hash spine. */
>     private int threshold;
>     /** Factor for computing size threshold. */
>     private final float loadFactor;
>     /** Maps hash value -> candidate handle value. */
>     private int[] spine;
>     /** Maps handle value -> next candidate handle value. */
>     private int[] next;
>     /** Maps handle value -> associated object. */
>     private Object[] objs;
>     /** Maps handle object hash -> associated object hash */
>     private int[] objHashes;
>     /** */
>     private int[] spineEmpty;
>     /** */
>     private int[] nextEmpty;
>     /**
>      * Creates new HandleTable with given capacity and load factor.
>      *
>      * @param initCap Initial capacity.
>      * @param loadFactor Load factor.
>      */
>     public GridHandleTable(int initCap, float loadFactor) {
>         this.loadFactor = loadFactor;
>         spine = new int[initCap];
>         next = new int[initCap];
>         objs = new Object[initCap];
>         objHashes = new int[initCap];
>         spineEmpty = new int[initCap];
>         nextEmpty = new int[initCap];
>         Arrays.fill(spineEmpty, -1);
>         Arrays.fill(nextEmpty, -1);
>         threshold = (int)(initCap * loadFactor);
>         clear();
>     }
>     /**
>      * Looks up and returns handle associated with given object, or -1 if
>      * no mapping found.
>      *
>      * @param obj Object.
>      * @return Handle.
>      */
>     public int lookup(Object obj) {
>     	int objHash = hash(obj);
>         int idx = objHash % spine.length;
>         if (size > 0) {
>             for (int i = spine[idx]; i >= 0; i = next[i])
>                 if (objs[i] == obj)
>                     return i;
>         }
>         if (size >= next.length)
>             growEntries();
>         if (size >= threshold) {
>             growSpine();
>             idx = objHash % spine.length;
>         }
>         insert(obj, size, idx, objHash);
>         size++;
>         return -1;
>     }
>     /**
>      * Resets table to its initial (empty) state.
>      */
>     public void clear() {
>         System.arraycopy(spineEmpty, 0, spine, 0, spineEmpty.length);
>         System.arraycopy(nextEmpty, 0, next, 0, nextEmpty.length);
>         Arrays.fill(objs, null);
>         Arrays.fill(objHashes, 0);
>         size = 0;
>     }
>     /**
>      * @return Returns objects that were added to handles table.
>      */
>     public Object[] objects() {
>         return objs;
>     }
>     /**
>      * Inserts mapping object -> handle mapping into table. Assumes table
>      * is large enough to accommodate new mapping.
>      *
>      * @param obj Object.
>      * @param handle Handle.
>      * @param idx Index.
>      */
>     private void insert(Object obj, int handle, int idx, int hash) {
>         objs[handle] = obj;
>         next[handle] = spine[idx];
>         spine[idx] = handle;
>         objHashes[handle] = hash;
>     }
>     /**
>      * Inserts mapping object -> handle mapping into table. Assumes table
>      * is large enough to accommodate new mapping.
>      *
>      * @param handle Handle.
>      * @param idx Index.
>      */
>     private void updateSpine(int handle, int idx) {
>         next[handle] = spine[idx];
>         spine[idx] = handle;
>     }
>     /**
>      * Expands the hash "spine" - equivalent to increasing the number of
>      * buckets in a conventional hash table.
>      */
>     private void growSpine() {
>         int size = (spine.length << 1) + 1;
>         spine = new int[size];
>         spineEmpty = new int[size];
>         threshold = (int)(spine.length * loadFactor);
>         Arrays.fill(spineEmpty, -1);
>         System.arraycopy(spineEmpty, 0, spine, 0, spineEmpty.length);
>         for (int i = 0; i < this.size; i++) {
>             updateSpine(i, objHashes[i] % spine.length);
>         }
>     }
>     /**
>      * Increases hash table capacity by lengthening entry arrays.
>      */
>     private void growEntries() {
>         int newLen = (next.length << 1) + 1;
>         int[] newNext = new int[newLen];
>         System.arraycopy(next, 0, newNext, 0, size);
>         next = newNext;
>         nextEmpty = new int[newLen];
>         Arrays.fill(nextEmpty, -1);
>         Object[] newObjs = new Object[newLen];
>         System.arraycopy(objs, 0, newObjs, 0, size);
>         int[] newObjHashes = new int[newLen];
>         System.arraycopy(objHashes, 0, newObjHashes, 0, size);
>         objs = newObjs;
>         objHashes = newObjHashes;
>     }
>     /**
>      * Returns hash value for given object.
>      *
>      * @param obj Object.
>      * @return Hash value.
>      */
>     private int hash(Object obj) {
>         return System.identityHashCode(obj) & 0x7FFFFFFF;
>     }
> }
> {code}



--
This message was sent by Atlassian Jira
(v8.3.4#803005)