All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.netty.buffer.SizeClasses Maven / Gradle / Ivy

Go to download

This artifact provides a single jar that contains all classes required to use remote EJB and JMS, including all dependencies. It is intended for use by those not using maven, maven users should just import the EJB and JMS BOM's instead (shaded JAR's cause lots of problems with maven, as it is very easy to inadvertently end up with different versions on classes on the class path).

There is a newer version: 34.0.0.Final
Show newest version
/*
 * Copyright 2020 The Netty Project
 *
 * The Netty Project 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:
 *
 *   https://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 io.netty.buffer;

import static io.netty.buffer.PoolThreadCache.*;

/**
 * SizeClasses requires {@code pageShifts} to be defined prior to inclusion,
 * and it in turn defines:
 * 

* LOG2_SIZE_CLASS_GROUP: Log of size class count for each size doubling. * LOG2_MAX_LOOKUP_SIZE: Log of max size class in the lookup table. * sizeClasses: Complete table of [index, log2Group, log2Delta, nDelta, isMultiPageSize, * isSubPage, log2DeltaLookup] tuples. * index: Size class index. * log2Group: Log of group base size (no deltas added). * log2Delta: Log of delta to previous size class. * nDelta: Delta multiplier. * isMultiPageSize: 'yes' if a multiple of the page size, 'no' otherwise. * isSubPage: 'yes' if a subpage size class, 'no' otherwise. * log2DeltaLookup: Same as log2Delta if a lookup table size class, 'no' * otherwise. *

* nSubpages: Number of subpages size classes. * nSizes: Number of size classes. * nPSizes: Number of size classes that are multiples of pageSize. * * smallMaxSizeIdx: Maximum small size class index. * * lookupMaxClass: Maximum size class included in lookup table. * log2NormalMinClass: Log of minimum normal size class. *

* The first size class and spacing are 1 << LOG2_QUANTUM. * Each group has 1 << LOG2_SIZE_CLASS_GROUP of size classes. * * size = 1 << log2Group + nDelta * (1 << log2Delta) * * The first size class has an unusual encoding, because the size has to be * split between group and delta*nDelta. * * If pageShift = 13, sizeClasses looks like this: * * (index, log2Group, log2Delta, nDelta, isMultiPageSize, isSubPage, log2DeltaLookup) *

* ( 0, 4, 4, 0, no, yes, 4) * ( 1, 4, 4, 1, no, yes, 4) * ( 2, 4, 4, 2, no, yes, 4) * ( 3, 4, 4, 3, no, yes, 4) *

* ( 4, 6, 4, 1, no, yes, 4) * ( 5, 6, 4, 2, no, yes, 4) * ( 6, 6, 4, 3, no, yes, 4) * ( 7, 6, 4, 4, no, yes, 4) *

* ( 8, 7, 5, 1, no, yes, 5) * ( 9, 7, 5, 2, no, yes, 5) * ( 10, 7, 5, 3, no, yes, 5) * ( 11, 7, 5, 4, no, yes, 5) * ... * ... * ( 72, 23, 21, 1, yes, no, no) * ( 73, 23, 21, 2, yes, no, no) * ( 74, 23, 21, 3, yes, no, no) * ( 75, 23, 21, 4, yes, no, no) *

* ( 76, 24, 22, 1, yes, no, no) */ final class SizeClasses implements SizeClassesMetric { static final int LOG2_QUANTUM = 4; private static final int LOG2_SIZE_CLASS_GROUP = 2; private static final int LOG2_MAX_LOOKUP_SIZE = 12; private static final int LOG2GROUP_IDX = 1; private static final int LOG2DELTA_IDX = 2; private static final int NDELTA_IDX = 3; private static final int PAGESIZE_IDX = 4; private static final int SUBPAGE_IDX = 5; private static final int LOG2_DELTA_LOOKUP_IDX = 6; private static final byte no = 0, yes = 1; final int pageSize; final int pageShifts; final int chunkSize; final int directMemoryCacheAlignment; final int nSizes; final int nSubpages; final int nPSizes; final int lookupMaxSize; final int smallMaxSizeIdx; private final int[] pageIdx2sizeTab; // lookup table for sizeIdx <= smallMaxSizeIdx private final int[] sizeIdx2sizeTab; // lookup table used for size <= lookupMaxClass // spacing is 1 << LOG2_QUANTUM, so the size of array is lookupMaxClass >> LOG2_QUANTUM private final int[] size2idxTab; SizeClasses(int pageSize, int pageShifts, int chunkSize, int directMemoryCacheAlignment) { int group = log2(chunkSize) - LOG2_QUANTUM - LOG2_SIZE_CLASS_GROUP + 1; //generate size classes //[index, log2Group, log2Delta, nDelta, isMultiPageSize, isSubPage, log2DeltaLookup] short[][] sizeClasses = new short[group << LOG2_SIZE_CLASS_GROUP][7]; int normalMaxSize = -1; int nSizes = 0; int size = 0; int log2Group = LOG2_QUANTUM; int log2Delta = LOG2_QUANTUM; int ndeltaLimit = 1 << LOG2_SIZE_CLASS_GROUP; //First small group, nDelta start at 0. //first size class is 1 << LOG2_QUANTUM for (int nDelta = 0; nDelta < ndeltaLimit; nDelta++, nSizes++) { short[] sizeClass = newSizeClass(nSizes, log2Group, log2Delta, nDelta, pageShifts); sizeClasses[nSizes] = sizeClass; size = sizeOf(sizeClass, directMemoryCacheAlignment); } log2Group += LOG2_SIZE_CLASS_GROUP; //All remaining groups, nDelta start at 1. for (; size < chunkSize; log2Group++, log2Delta++) { for (int nDelta = 1; nDelta <= ndeltaLimit && size < chunkSize; nDelta++, nSizes++) { short[] sizeClass = newSizeClass(nSizes, log2Group, log2Delta, nDelta, pageShifts); sizeClasses[nSizes] = sizeClass; size = normalMaxSize = sizeOf(sizeClass, directMemoryCacheAlignment); } } //chunkSize must be normalMaxSize assert chunkSize == normalMaxSize; int smallMaxSizeIdx = 0; int lookupMaxSize = 0; int nPSizes = 0; int nSubpages = 0; for (int idx = 0; idx < nSizes; idx++) { short[] sz = sizeClasses[idx]; if (sz[PAGESIZE_IDX] == yes) { nPSizes++; } if (sz[SUBPAGE_IDX] == yes) { nSubpages++; smallMaxSizeIdx = idx; } if (sz[LOG2_DELTA_LOOKUP_IDX] != no) { lookupMaxSize = sizeOf(sz, directMemoryCacheAlignment); } } this.smallMaxSizeIdx = smallMaxSizeIdx; this.lookupMaxSize = lookupMaxSize; this.nPSizes = nPSizes; this.nSubpages = nSubpages; this.nSizes = nSizes; this.pageSize = pageSize; this.pageShifts = pageShifts; this.chunkSize = chunkSize; this.directMemoryCacheAlignment = directMemoryCacheAlignment; //generate lookup tables this.sizeIdx2sizeTab = newIdx2SizeTab(sizeClasses, nSizes, directMemoryCacheAlignment); this.pageIdx2sizeTab = newPageIdx2sizeTab(sizeClasses, nSizes, nPSizes, directMemoryCacheAlignment); this.size2idxTab = newSize2idxTab(lookupMaxSize, sizeClasses); } //calculate size class private static short[] newSizeClass(int index, int log2Group, int log2Delta, int nDelta, int pageShifts) { short isMultiPageSize; if (log2Delta >= pageShifts) { isMultiPageSize = yes; } else { int pageSize = 1 << pageShifts; int size = calculateSize(log2Group, nDelta, log2Delta); isMultiPageSize = size == size / pageSize * pageSize? yes : no; } int log2Ndelta = nDelta == 0? 0 : log2(nDelta); byte remove = 1 << log2Ndelta < nDelta? yes : no; int log2Size = log2Delta + log2Ndelta == log2Group? log2Group + 1 : log2Group; if (log2Size == log2Group) { remove = yes; } short isSubpage = log2Size < pageShifts + LOG2_SIZE_CLASS_GROUP? yes : no; int log2DeltaLookup = log2Size < LOG2_MAX_LOOKUP_SIZE || log2Size == LOG2_MAX_LOOKUP_SIZE && remove == no ? log2Delta : no; return new short[] { (short) index, (short) log2Group, (short) log2Delta, (short) nDelta, isMultiPageSize, isSubpage, (short) log2DeltaLookup }; } private static int[] newIdx2SizeTab(short[][] sizeClasses, int nSizes, int directMemoryCacheAlignment) { int[] sizeIdx2sizeTab = new int[nSizes]; for (int i = 0; i < nSizes; i++) { short[] sizeClass = sizeClasses[i]; sizeIdx2sizeTab[i] = sizeOf(sizeClass, directMemoryCacheAlignment); } return sizeIdx2sizeTab; } private static int calculateSize(int log2Group, int nDelta, int log2Delta) { return (1 << log2Group) + (nDelta << log2Delta); } private static int sizeOf(short[] sizeClass, int directMemoryCacheAlignment) { int log2Group = sizeClass[LOG2GROUP_IDX]; int log2Delta = sizeClass[LOG2DELTA_IDX]; int nDelta = sizeClass[NDELTA_IDX]; int size = calculateSize(log2Group, nDelta, log2Delta); return alignSizeIfNeeded(size, directMemoryCacheAlignment); } private static int[] newPageIdx2sizeTab(short[][] sizeClasses, int nSizes, int nPSizes, int directMemoryCacheAlignment) { int[] pageIdx2sizeTab = new int[nPSizes]; int pageIdx = 0; for (int i = 0; i < nSizes; i++) { short[] sizeClass = sizeClasses[i]; if (sizeClass[PAGESIZE_IDX] == yes) { pageIdx2sizeTab[pageIdx++] = sizeOf(sizeClass, directMemoryCacheAlignment); } } return pageIdx2sizeTab; } private static int[] newSize2idxTab(int lookupMaxSize, short[][] sizeClasses) { int[] size2idxTab = new int[lookupMaxSize >> LOG2_QUANTUM]; int idx = 0; int size = 0; for (int i = 0; size <= lookupMaxSize; i++) { int log2Delta = sizeClasses[i][LOG2DELTA_IDX]; int times = 1 << log2Delta - LOG2_QUANTUM; while (size <= lookupMaxSize && times-- > 0) { size2idxTab[idx++] = i; size = idx + 1 << LOG2_QUANTUM; } } return size2idxTab; } @Override public int sizeIdx2size(int sizeIdx) { return sizeIdx2sizeTab[sizeIdx]; } @Override public int sizeIdx2sizeCompute(int sizeIdx) { int group = sizeIdx >> LOG2_SIZE_CLASS_GROUP; int mod = sizeIdx & (1 << LOG2_SIZE_CLASS_GROUP) - 1; int groupSize = group == 0? 0 : 1 << LOG2_QUANTUM + LOG2_SIZE_CLASS_GROUP - 1 << group; int shift = group == 0? 1 : group; int lgDelta = shift + LOG2_QUANTUM - 1; int modSize = mod + 1 << lgDelta; return groupSize + modSize; } @Override public long pageIdx2size(int pageIdx) { return pageIdx2sizeTab[pageIdx]; } @Override public long pageIdx2sizeCompute(int pageIdx) { int group = pageIdx >> LOG2_SIZE_CLASS_GROUP; int mod = pageIdx & (1 << LOG2_SIZE_CLASS_GROUP) - 1; long groupSize = group == 0? 0 : 1L << pageShifts + LOG2_SIZE_CLASS_GROUP - 1 << group; int shift = group == 0? 1 : group; int log2Delta = shift + pageShifts - 1; int modSize = mod + 1 << log2Delta; return groupSize + modSize; } @Override public int size2SizeIdx(int size) { if (size == 0) { return 0; } if (size > chunkSize) { return nSizes; } size = alignSizeIfNeeded(size, directMemoryCacheAlignment); if (size <= lookupMaxSize) { //size-1 / MIN_TINY return size2idxTab[size - 1 >> LOG2_QUANTUM]; } int x = log2((size << 1) - 1); int shift = x < LOG2_SIZE_CLASS_GROUP + LOG2_QUANTUM + 1 ? 0 : x - (LOG2_SIZE_CLASS_GROUP + LOG2_QUANTUM); int group = shift << LOG2_SIZE_CLASS_GROUP; int log2Delta = x < LOG2_SIZE_CLASS_GROUP + LOG2_QUANTUM + 1 ? LOG2_QUANTUM : x - LOG2_SIZE_CLASS_GROUP - 1; int mod = size - 1 >> log2Delta & (1 << LOG2_SIZE_CLASS_GROUP) - 1; return group + mod; } @Override public int pages2pageIdx(int pages) { return pages2pageIdxCompute(pages, false); } @Override public int pages2pageIdxFloor(int pages) { return pages2pageIdxCompute(pages, true); } private int pages2pageIdxCompute(int pages, boolean floor) { int pageSize = pages << pageShifts; if (pageSize > chunkSize) { return nPSizes; } int x = log2((pageSize << 1) - 1); int shift = x < LOG2_SIZE_CLASS_GROUP + pageShifts ? 0 : x - (LOG2_SIZE_CLASS_GROUP + pageShifts); int group = shift << LOG2_SIZE_CLASS_GROUP; int log2Delta = x < LOG2_SIZE_CLASS_GROUP + pageShifts + 1? pageShifts : x - LOG2_SIZE_CLASS_GROUP - 1; int mod = pageSize - 1 >> log2Delta & (1 << LOG2_SIZE_CLASS_GROUP) - 1; int pageIdx = group + mod; if (floor && pageIdx2sizeTab[pageIdx] > pages << pageShifts) { pageIdx--; } return pageIdx; } // Round size up to the nearest multiple of alignment. private static int alignSizeIfNeeded(int size, int directMemoryCacheAlignment) { if (directMemoryCacheAlignment <= 0) { return size; } int delta = size & directMemoryCacheAlignment - 1; return delta == 0? size : size + directMemoryCacheAlignment - delta; } @Override public int normalizeSize(int size) { if (size == 0) { return sizeIdx2sizeTab[0]; } size = alignSizeIfNeeded(size, directMemoryCacheAlignment); if (size <= lookupMaxSize) { int ret = sizeIdx2sizeTab[size2idxTab[size - 1 >> LOG2_QUANTUM]]; assert ret == normalizeSizeCompute(size); return ret; } return normalizeSizeCompute(size); } private static int normalizeSizeCompute(int size) { int x = log2((size << 1) - 1); int log2Delta = x < LOG2_SIZE_CLASS_GROUP + LOG2_QUANTUM + 1 ? LOG2_QUANTUM : x - LOG2_SIZE_CLASS_GROUP - 1; int delta = 1 << log2Delta; int delta_mask = delta - 1; return size + delta_mask & ~delta_mask; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy