对于内存减少Java的整数标志和位操作

使用整数标志和位运算降低大批量对象的内存占用的有效途径?

  • 内存占用

    这是我的理解,通常是boolean存储为int在JVM实现。 它是否正确? 在这种情况下,肯定是32的标志代表了大量的内存占用减少。

    虽然当然JVM实现而变化,因此这可能不总是这种情况。

  • 性能

    这是我的理解是CPU是非常数量驱动和位运算大约有效率的东西进来计算。

    有没有性能上的损失 - 甚至获得 - 用在布尔运算位操作?

  • 备择方案

    是否有完成同样的事情的一个更好的办法? 是否一个枚举允许的标志,即结合FLAGX = FLAG1 | FLAG2 FLAGX = FLAG1 | FLAG2

示例代码

注意最后一个方法propogateMove()是递归的,可称为很多每秒数百次,对我们的应用程序的响应能力,旗帜,以避免逻辑位,因此使用和调用其他方法有直接的影响。

// FLAGS helper functions private final void setclear(int mask, boolean set) { if (set) set(mask); else clear(mask); } private final void set(int mask) { flags |= mask; } private final void clear(int mask) { flags &= ~mask; } private final boolean test(int mask) { return ((flags & mask) == mask); } // Flags ////////////////////////////////////////////////////////////////////// private static final boolean HORIZONTAL = true; private static final boolean VERTICAL = false; private static final int ORIENT = 0x00000001; private static final int DISPLAY = 0x00000002; private static final int HSHRINK = 0x00000004; private static final int VSHRINK = 0x00000008; private static final int SHRINK = HSHRINK | VSHRINK; private static final int TILE_IMAGE = 0x00000010; private static final int CURSOR = 0x00000020; private static final int MOUSEINSIDE = 0x00000040; private static final int MOUSEINSIDE_BLOCKED = 0x00000080; private static final int CONSTRAIN = 0x00000100; private static final int CONSTRAIN_DESCENDENT = 0x00000200; private static final int PLACE = 0x00000400; private static final int PLACE_DESCENDENT = 0x00000800; private static final int REFLOW = CONSTRAIN | CONSTRAIN_DESCENDENT | PLACE | PLACE_DESCENDENT; private static final int PACK = 0x00001000; private static final int CLIP = 0x00002000; private static final int HAS_WIDTH_SLACK = 0x00004000; private static final int HAS_HEIGHT_SLACK = 0x00008000; private static final int ALIGN_TOP = 0x00010000; private static final int ALIGN_BOTTOM = 0x00020000; private static final int ALIGN_LEFT = 0x00040000; private static final int ALIGN_RIGHT = 0x00080000; private static final int ALIGNS = ALIGN_TOP | ALIGN_BOTTOM | ALIGN_LEFT | ALIGN_RIGHT; private static final int ALIGN_TOPLEFT = ALIGN_TOP | ALIGN_LEFT; private static final int ALIGN_TOPRIGHT = ALIGN_TOP | ALIGN_RIGHT; private static final int ALIGN_BOTTOMLEFT = ALIGN_BOTTOM | ALIGN_LEFT; private static final int ALIGN_BOTTOMRIGHT = ALIGN_BOTTOM | ALIGN_RIGHT; private static final int ENTER_TRAP = 0x00100000; private static final int LEAVE_TRAP = 0x00200000; private static final int _MOVE_TRAP = 0x00400000; private static final int MOVE_TRAP = 0x00800000; private static final int CHILDREN_READ_TRAP = 0x01000000; private static final int CHILDREN_TRAP = 0x02000000; private static final int PLACE_CLEAN = 0x03000000; private static final int SHRINK_TRAP = 0x04000000; private static final int HSHRINK_TRAP = 0x10000000; private static final int VSHRINK_TRAP = 0x20000000; //private static final int UNUSED = 0x40000000; //private static final int UNUSED = 0x80000000; // Flags in switch //////////////////////////////////////////////////////////// /** get align value as a string from align flags */ private JS alignToJS() { switch(flags & ALIGNS) { case (ALIGN_TOPLEFT): return SC_align_topleft; case (ALIGN_BOTTOMLEFT): return SC_align_bottomleft; case (ALIGN_TOPRIGHT): return SC_align_topright; case (ALIGN_BOTTOMRIGHT): return SC_align_bottomright; case ALIGN_TOP: return SC_align_top; case ALIGN_BOTTOM: return SC_align_bottom; case ALIGN_LEFT: return SC_align_left; case ALIGN_RIGHT: return SC_align_right; case 0: // CENTER return SC_align_center; default: throw new Error("This should never happen; invalid alignment flags: " + (flags & ALIGNS)); } } // Flags in logic ///////////////////////////////////////////////////////////// private final boolean propagateMove(int mousex, int mousey) throws JSExn { // start with pre-event _Move which preceeds Enter/Leave if (test(_MOVE_TRAP)) { if (Interpreter.CASCADE_PREVENTED == justTriggerTraps(SC__Move, JSU.T)) { // _Move cascade prevention induces Leave propagateLeave(); // propagate cascade prevention return true; } } // REMARK: anything from here on in is a partial interruption relative // to this box so we can not call propagateLeave() directly upon it int i; boolean interrupted = false; if (!test(PACK)) { // absolute layout - allows for interruption by overlaying siblings for (Box b = getChild(i=treeSize()-1); b != null; b = getChild(--i)) { if (!b.test(DISPLAY)) { continue; } if (interrupted) { b.propagateLeave(); continue; } int b_mx = mousex-getXInParent(b); int b_my = mousey-getYInParent(b); if (b.inside(b_mx, b_my)) { if (b.propagateMove(b_mx, b_my)) { interrupted = true; } } else { b.propagateLeave(); } } } else { // packed layout - interrupted still applies, plus packedhit shortcut boolean packedhit = false; for (Box b = getChild(i=treeSize()-1); b != null; b = getChild(--i)) { if (!b.test(DISPLAY)) { continue; } if (packedhit) { b.propagateLeave(); continue; } int b_mx = mousex-getXInParent(b); int b_my = mousey-getYInParent(b); if (b.inside(b_mx, b_my)) { packedhit = true; if (b.propagateMove(b_mx, b_my)) { interrupted = true; } } else { b.propagateLeave(); } } } // child prevented cascade during _Move/Move which blocks // Enter on this box - invoking Leave if necessary if (interrupted) { if (test(MOUSEINSIDE)) { if (!test(MOUSEINSIDE_BLOCKED)) { // mouse previously inside, now blocked so invoke Leave set(MOUSEINSIDE_BLOCKED); if (test(LEAVE_TRAP)) { justTriggerTraps(SC_Leave, JSU.T); } } } else { // mouse not previously inside, Enter not yet triggered, so // do not invoke Leave set(MOUSEINSIDE); set(MOUSEINSIDE_BLOCKED); } // propagate cascade prevention return true; } // set cursor if applicable to this box if (test(CURSOR)) { Surface s = getSurface(); if (s!=null && !s.cursorset) { s.cursor = JSU.toString(getAndTriggerTraps(SC_cursor)); s.cursorset = true; } } // fire Enter traps if (!test(MOUSEINSIDE)) { set(MOUSEINSIDE); if (test(ENTER_TRAP)) { justTriggerTraps(SC_Enter, JSU.T); } } // finish post-event Move which follows Enter/Leave if (test(MOVE_TRAP)) { if (Interpreter.CASCADE_PREVENTED == justTriggerTraps(SC_Move, JSU.T)) { // propagate cascade prevention return true; } } // propagation uninterrupted return false; }

--------------解决方案-------------

这是我的理解是常用的布尔被存储为JVM实现一个int。 它是否正确?

这取决于JVM实现,当然,但可能是主流的CPU实现如此。

在这种情况下,肯定是32的标志代表了大量的内存占用减少。

如果你确实有32个标志中的一类,而大量的类的实例,是的。 如果你从来没有超过几百情况下,这是不值得担心。

这是我的理解是CPU是非常数量驱动和位运算大约有效率的东西进来计算。

这是真的。

有没有性能上的损失 - 甚至获得 - 用在布尔运算位操作?

这也取决于内存使用情况。 如果你只有几个对象的工作非常集中,按位操作可能会慢下来。 如果你有大量的对象,减少内存可能会提高性能,很多由于更好的缓存行为。

是否有完成同样的事情的一个更好的办法? 是否一个枚举允许标志即FLAGX = FLAG1组合| FLAG2?

而是自己做位操作,你可以(也应该)使用BitSet 。 是的,这将是,即使你可以用枚举和工作的清洁EnumSet ,但如果你有一些枚举每几个元素,它可能不会产生预期的节省内存,由于开销多EnumSet实例。

是的,一个布尔值存储为一个32位的int。 方法签名布尔和整数区别,但否则将被视为相同。 这是JVM的字节代码规范的一部分。

直接的Java地图到做同样的位运算,所以这的确是相当快的CPU上一条指令的位操作。 当然,这是更快地保持了自己的32位字的每个值(那么你并不需要在所有做任何按位运算)。 您将节省内存,并使用你的方法花费更多的CPU周期。

Java没有运营商相结合的枚举,我看不出这将使任何意义反正...

使用整数标志和位运算降低大批量对象的内存占用的有效途径?

如果一个对象有大量的这些标志,有这些对象数量巨大(或减少堆使用是一个关键问题),那么这可能是一个有价值的微型优化。 否则,没有(IMO)。

这里的问题是,它使你的代码难以阅读和更加脆弱。 所以,你如果真的内存使用量是一个关键问题应只考虑它。

正如你不能相信布尔值存储为位或整数(我认为后者是实际执行),是的,我觉得位掩码和标志做提高性能。

我用他们的一些项目。 他们是难读,但我从不介意有关,因为我的观点是,每个程序员都应该理解二进制表示法和算术。

只是一个建议:作为Java 7中,我们可以定义数字文字是这样的:

private static final int ENTER_TRAP = 0b00000000000100000000000000000000;

而即使是这样的:

private static final int ENTER_TRAP = 0b0000_0000_0001_0000_0000_0000_0000_0000;

分类:java的 时间:2015-03-15 人气:0
分享到:

相关文章

Copyright (C) 55228885.com, All Rights Reserved.

55228885 版权所有 京ICP备15002868号

processed in 1.137 (s). 10 q(s)