对于内存减少Java的整数标志和位操作 [英] Java integer flag and bitwise operations for memory reduction

查看:292
本文介绍了对于内存减少Java的整数标志和位操作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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


  • 内存占用

    这是我的理解,通常是布尔是在JVM实现存储为 INT 。它是否正确?在这种情况下,肯定是32标志重新present大容量内存减少。

    虽然当然JVM实现而变化,因此这可能不总是这样的。


  • 性能

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

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


  • 替代

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



例code

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

  // FLAGS辅助功能
私人最终无效setclear(INT面具,布尔集){如果(套)集(面罩);否则清除(面罩); }
私人最终无效集(INT面罩){标志| =口罩; }
私人最终无效明确(INT面罩){标志和放大器; =〜口罩; }
私人最终布尔测试(INT面罩){回报((标志&安培;面罩)==面罩); }//标志/////////////////////////////////////////////// ///////////////////////私有静态最终布尔水平= TRUE;
私有静态最终布尔垂直= FALSE;私有静态最终诠释东方= 00000001;
私有静态最终诠释DISPLAY = 0x00000002;
私有静态最终诠释HSHRINK = 0x00000004;
私有静态最终诠释VSHRINK = 0x00000008;
私有静态最终诠释SHRINK = HSHRINK | VSHRINK;私有静态最终诠释TILE_IMAGE = 0x00000010;
私有静态最终诠释CURSOR = 0x00000020;
私有静态最终诠释MOUSEINSIDE = 0x00000040;
私有静态最终诠释MOUSEINSIDE_BLOCKED = 0x00000080;私有静态最终诠释约束= 0x00000100;
私有静态最终诠释CONSTRAIN_DESCENDENT = 0x00000200;
私有静态最终诠释PLACE = 0x00000400时;
私有静态最终诠释PLACE_DESCENDENT = 0x00000800;
私有静态最终诠释回流=限制| CONSTRAIN_DESCENDENT | PLACE | PLACE_DESCENDENT;私有静态最终诠释PACK = 0x00001000;
私有静态最终诠释CLIP = 0x00002000;
私有静态最终诠释HAS_WIDTH_SLACK = 0x00004000;
私有静态最终诠释HAS_HEIGHT_SLACK = 0x00008000;私有静态最终诠释ALIGN_TOP = 0x00010000在;
私有静态最终诠释ALIGN_BOTTOM = 0x00020000;
私有静态最终诠释ALIGN_LEFT = 0x00040000;
私有静态最终诠释ALIGN_RIGHT = 0x00080000;
私有静态最终诠释对齐= ALIGN_TOP | ALIGN_BOTTOM | ALIGN_LEFT | ALIGN_RIGHT;
私有静态最终诠释ALIGN_TOPLEFT = ALIGN_TOP | ALIGN_LEFT;
私有静态最终诠释ALIGN_TOPRIGHT = ALIGN_TOP | ALIGN_RIGHT;
私有静态最终诠释ALIGN_BOTTOMLEFT = ALIGN_BOTTOM | ALIGN_LEFT;
私有静态最终诠释ALIGN_BOTTOMRIGHT = ALIGN_BOTTOM | ALIGN_RIGHT;私有静态最终诠释ENTER_TRAP = 0x00100000;
私有静态最终诠释LEAVE_TRAP = 0x00200000;
私有静态最终诠释_MOVE_TRAP = 0x00400000;
私有静态最终诠释MOVE_TRAP = 0x00800000;私有静态最终诠释CHILDREN_READ_TRAP =为0x01000000;
私有静态最终诠释CHILDREN_TRAP = 0x02000000;
私有静态最终诠释PLACE_CLEAN = 0x03000000;私有静态最终诠释SHRINK_TRAP = 0x04000000;
私有静态最终诠释HSHRINK_TRAP = 0x10000000处;
私有静态最终诠释VSHRINK_TRAP = 0x20000000;//私有静态最终诠释UNUSED = 0x40000000之后;
//私有静态最终诠释UNUSED = 0x80000000的;
//在开关标志///////////////////////////////////////////// //////////////// **得到对齐值从对准标志的字符串* /
私人JS alignToJS(){
    开关(旗&放大器;对齐){
        案例(ALIGN_TOPLEFT):
            返回SC_align_topleft;
        案例(ALIGN_BOTTOMLEFT):
            返回SC_align_bottomleft;
        案例(ALIGN_TOPRIGHT):
            返回SC_align_topright;
        案例(ALIGN_BOTTOMRIGHT):
            返回SC_align_bottomright;
        案例ALIGN_TOP:
            返回SC_align_top;
        案例ALIGN_BOTTOM:
            返回SC_align_bottom;
        案例ALIGN_LEFT:
            返回SC_align_left;
        案例ALIGN_RIGHT:
            返回SC_align_right;
        案件0:// CENTER
            返回SC_align_center;
        默认:
            抛出新的错误(这绝不应该发生;无效对齐标志:+(标志和放大器;对齐));
    }
}
//逻辑标志///////////////////////////////////////////// ////////////////私人最终布尔propagateMove(INT mousex,诠释像老鼠)抛出JSExn {
    //使用pre-事件_Move其中preceeds进入/离开启动
    如果(试验(_MOVE_TRAP)){
        如果(国际米兰preter.CASCADE_ preVENTED == justTriggerTraps(SC__Move,JSU.T)){
            // _Move级联prevention诱导休假
            propagateLeave();
            //传播级联prevention
            返回true;
        }
    }    //备注:任何东西从这里开始为部分相对中断
    //这个箱子,所以我们不能直接呼吁它propagateLeave()
    INT I;
    布尔中断=假;    如果(!测试(PACK)){
        //绝对布局 - 允许中断通过叠加的兄弟姐妹
        对于(专栏B = getChild(I =的TreeSize() - 1);!B = NULL; B = getChild( - I)){
            如果(!b.test(显示)){
                继续;
            }
            如果(中断){
                b.propagateLeave();
                继续;
            }
            INT b_mx = mousex-getXInParent(B);
            INT b_my =像老鼠-getYInParent(B);
            如果(b.inside(b_mx,b_my)){
                如果(b.propagateMove(b_mx,b_my)){
                    中断=真实的;
                }
            }其他{
                b.propagateLeave();
            }
        }
    }其他{
        //包装设计 - 打断仍然适用,加上packedhit快捷方式
        布尔packedhit = FALSE;
        对于(专栏B = getChild(I =的TreeSize() - 1);!B = NULL; B = getChild( - I)){
            如果(!b.test(显示)){
                继续;
            }
            如果(packedhit){
                b.propagateLeave();
                继续;
            }
            INT b_mx = mousex-getXInParent(B);
            INT b_my =像老鼠-getYInParent(B);
            如果(b.inside(b_mx,b_my)){
                packedhit = TRUE;
                如果(b.propagateMove(b_mx,b_my)){
                    中断=真实的;
                }
            }其他{
                b.propagateLeave();
            }
        }
    }    //子$ P $中_Move /移动pvented级联的块
    //输入此框 - 必要时调用休假
    如果(中断){
        如果(试验(MOUSEINSIDE)){
            如果(!试验(MOUSEINSIDE_BLOCKED)){
                //鼠标previously里面,现在堵塞了,所以调用休假
                集(MOUSEINSIDE_BLOCKED);
                如果(试验(LEAVE_TRAP)){
                    justTriggerTraps(SC_Leave,JSU.T);
                }
            }
        }其他{
            //鼠标没有previously里面,输入尚未触发,所以
            //不要调用休假
            集(MOUSEINSIDE);
            集(MOUSEINSIDE_BLOCKED);
        }
        //传播级联prevention
        返回true;
    }    //设置光标如果适用于这个盒子
    如果(测试(光标)){
        表面S = getSurface();
        如果(S = NULL&放大器;!&安培;!s.cursorset){
            s.cursor = JSU.toString(getAndTriggerTraps(SC_cursor));
            s.cursorset = TRUE;
        }
    }    //火进入陷阱
    如果(!试验(MOUSEINSIDE)){
        集(MOUSEINSIDE);
        如果(试验(ENTER_TRAP)){
            justTriggerTraps(SC_Enter,JSU.T);
        }
    }    随后输入//完成事后移动/离开
    如果(试验(MOVE_TRAP)){
        如果(国际米兰preter.CASCADE_ preVENTED == justTriggerTraps(SC_Move,JSU.T)){
            //传播级联prevention
            返回true;
        }
    }    //不间断地传播
    返回false;
}


解决方案

  

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


这取决于JVM实现的课程,但可能是真实的主流CPU的实现。


  

在这种情况下,肯定是32标志重新present大容量内存减少。


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


  

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


这是真实的。


  

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


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


  

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


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

Is using an integer flag and bitwise operations an effective way of reducing the memory footprint of high volume Objects?

  • Memory Footprint

    It is my understanding that commonly a boolean is stored as an int in a JVM implementation. Is this correct? In which case surely the 32 flags represent a large memory footprint reduction.

    Although of course the JVM implementations vary, so this may not always be the case.

  • Performance

    It is my understanding that CPUs are very number driven and bitwise operations are about as efficient as things come in computing.

    Is there a performance penalty - or even gain - to using bitwise operations over boolean operations?

  • Alternatives

    Is there a better way of accomplishing the same thing? Does an Enum allow the combination of flags i.e. FLAGX = FLAG1 | FLAG2?


Example Code

Note the last method propogateMove() is recursive and may be called many hundreds of times per second and has a direct effect on the responsiveness of our application, hence the usage of flags to avoid logic bits and calling other methods.

// 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;
}

解决方案

It is my understanding that commonly a boolean is stored as an int in a JVM implementation. Is this correct?

It depends on the JVM implementation of course, but is probably true for implementations on mainstream CPUs.

In which case surely the 32 flags represent a large memory footprint reduction.

If you actually have 32 flags in a class, and a large number of instances of that class, yes. If you never have more than a few hundred instances, it's not worth worrying about.

It is my understanding that CPUs are very number driven and bitwise operations are about as efficient as things come in computing.

This is true.

Is there a performance penalty - or even gain - to using bitwise operations over boolean operations?

That depends also on the memory usage. If you work very intensively with only a few objects, the bitwise operations may slow things down. If you have lots of objects, the reduced memory will probably improve performance a lot due to better caching behaviour.

Is there a better way of accomplishing the same thing? Does an Enum allow the combination of flags i.e. FLAGX = FLAG1 | FLAG2?

Instead of doing the bitwise operations yourself, you can (and should) use a BitSet. And yes, it would be even cleaner if you could work with Enums and an EnumSet, but if you have a number of enums with a few elements each, it would probably not yield the desired memory savings, due to the overhead for multiple EnumSet instances.

这篇关于对于内存减少Java的整数标志和位操作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆