| /* |
| * 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.sysds.utils; |
| |
| /** |
| * Memory Estimates is a helper class containing static classes that estimate the memory requirements of different types |
| * of objects in java. All estimates are worst case JVM x86-64bit uncompressed object pointers. |
| * |
| * This in practice means that the objects are most commonly smaller, for instance the object references are often time. |
| * |
| * If the memory pressure is low (there is a low number of allocated objects) then object pointers are 4 bits. |
| */ |
| public class MemoryEstimates { |
| |
| // private static final Log LOG = LogFactory.getLog(MemoryEstimates.class.getName()); |
| |
| /** |
| * Get the worst case memory usage of an java.util.BitSet java object. |
| * |
| * @param length The length of the array. |
| * @return The memory estimate in bytes |
| */ |
| public static double bitSetCost(long length) { |
| double size = 0; |
| size += 8; // object reference |
| size += longArrayCost(length / 64 + (length % 64 > 0 ? 1 : 0)); |
| size += 4; // words in Use |
| size += 1; // size is Sticky |
| size += 3; // padding. |
| return size; |
| } |
| |
| /** |
| * Get the worst case memory usage of an array of booleans. |
| * |
| * Unfortunately in java booleans are allocated as bytes. |
| * |
| * @param length The length of the array. |
| * @return The memory estimate in bytes. |
| */ |
| public static double booleanArrayCost(long length) { |
| return byteArrayCost(length); |
| } |
| |
| /** |
| * Get the worst case memory usage of an array of bytes. |
| * |
| * @param length The length of the array. |
| * @return The memory estimate in bytes |
| */ |
| public static double byteArrayCost(long length) { |
| long size = 0; |
| size += 8; // Byte array Reference |
| size += 20; // Byte array Object header |
| if(length <= 4) { // byte array fills out the first 4 bytes differently than the later bytes. |
| size += 4; |
| } |
| else { // byte array pads to next 8 bytes after the first 4. |
| size += length; |
| double diff = (length - 4) % 8; |
| if(diff > 0) { |
| size += 8 - diff; |
| } |
| } |
| return size; |
| } |
| |
| /** |
| * Get the worst case memory usage of an array of chars. |
| * |
| * @param length The length of the array. |
| * @return The memory estimate in bytes |
| */ |
| public static double charArrayCost(long length) { |
| double size = 0; |
| size += 8; // char array Reference |
| size += 20; // char array Object header |
| if(length <= 2) { // char array fills out the first 2 chars differently than the later bytes. |
| size += 4; |
| } |
| else { |
| size += length * 2;// 2 bytes per char |
| double diff = (length * 2 - 4) % 8; |
| if(diff > 0) { |
| size += 8 - diff; // next object alignment |
| } |
| } |
| return size; |
| } |
| |
| /** |
| * Get the worst case memory usage of an array of integers. |
| * |
| * @param length The length of the array. |
| * @return The memory estimate in bytes |
| */ |
| public static double intArrayCost(long length) { |
| double size = 0; |
| size += 8; // _ptr int[] reference |
| size += 20; // int array Object header |
| if(length <= 1) { |
| size += 4; |
| } |
| else { |
| size += 4d * length; // offsets 4 bytes per int |
| if(length % 2 == 0) |
| size += 4; |
| } |
| return size; |
| } |
| |
| /** |
| * Get the worst case memory usage of an array of integers. |
| * |
| * @param length The length of the array. |
| * @return The memory estimate in bytes. |
| */ |
| public static double floatArrayCost(long length) { |
| // exact same size as intArrayCost |
| return intArrayCost(length); |
| } |
| |
| /** |
| * Get the worst case memory usage of an array of doubles. |
| * |
| * @param length The length of the array. |
| * @return The memory estimate in bytes |
| */ |
| public static final double doubleArrayCost(long length) { |
| double size = 0; |
| size += 8; // _values double array reference |
| size += 20; // double array object header |
| size += 4; // padding inside double array object to align to 8 bytes. |
| size += 8d * length; // Each double fills 8 Bytes |
| return size; |
| } |
| |
| /** |
| * Get the worst case memory usage for an array of objects. |
| * |
| * Note this does not take into account each objects allocated variables, just the objects themselves. |
| * |
| * @param length The length of the array. |
| * @return The memory estimate in bytes |
| */ |
| public static final double objectArrayCost(long length) { |
| double size = 0; |
| size += 8d; // reference to array |
| size += 20d; // header |
| size += 4d; // padding before first reference |
| size += 8d * length; // references to all objects. |
| return size; |
| } |
| |
| /** |
| * Get the worst case memory usage for an array of longs |
| * |
| * @param length The length of the array. |
| * @return The memory estimate in bytes |
| */ |
| public static final double longArrayCost(long length) { |
| // exactly the same size as a double array |
| return doubleArrayCost(length); |
| } |
| |
| /** |
| * Get the worst case memory usage of an array containing strings. |
| * |
| * In case anyone is wondering ... strings are expensive. |
| * |
| * @param strings The strings array. |
| * @return The array memory cost |
| */ |
| public static final double stringArrayCost(String[] strings) { |
| double size = 0; |
| int i = 0; |
| int by8 = strings.length - strings.length %8 ; |
| for(;i < by8; i+= 8) |
| size += stringArrayCostVec8(strings, i); |
| for(; i < strings.length; i++) |
| size += stringCost(strings[i]); |
| return size; |
| } |
| |
| private static final double stringArrayCostVec8(String[] strings, int r){ |
| long size = 0; |
| size += stringCost(strings[r]); |
| size += stringCost(strings[r+1]); |
| size += stringCost(strings[r+2]); |
| size += stringCost(strings[r+3]); |
| size += stringCost(strings[r+4]); |
| size += stringCost(strings[r+5]); |
| size += stringCost(strings[r+6]); |
| size += stringCost(strings[r+7]); |
| return size; |
| } |
| |
| public static final double stringArrayCost(int length, int avgStringLength){ |
| // if null 16 object + 8 array ref |
| return stringCost(avgStringLength) * length + 24.0d; |
| } |
| |
| /** |
| * Get the worst case memory usage of a single string. |
| * |
| * In case anyone is wondering ... strings are expensive. |
| * |
| * @param value The String to measure |
| * @return The size in memory. |
| */ |
| public static long stringCost(String value) { |
| // if null 16 object + 8 array ref |
| return value == null ? 24L : stringCost(value.length()); // char array |
| } |
| |
| /** |
| * Get the worst case memory usage of a single string, assuming given length. |
| * |
| * @param length The length of the string |
| * @return The size in memory |
| */ |
| public static long stringCost(long length) { |
| // 16 object |
| // 4 hash |
| // 8 array ref |
| // 32 char array |
| // total base : 60 |
| return 60L + length * 2L; // char array |
| } |
| |
| } |