Skip to content

Commit

Permalink
Optimize MathUtil.align to avoid modulo/division
Browse files Browse the repository at this point in the history
  • Loading branch information
shipilev committed Oct 14, 2020
1 parent fbe7a57 commit c47d165
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 12 deletions.
32 changes: 20 additions & 12 deletions jol-core/src/main/java/org/openjdk/jol/util/MathUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -62,19 +62,27 @@ public static int pow2(int power) {
return p;
}

public static int align(int addr, int align) {
if ((addr % align) == 0) {
return addr;
} else {
return ((addr / align) + 1) * align;
}
/**
* Aligns the argument to the given alignment.
* Alignment should be a power of two.
*
* @param v value to align
* @param a alignment, should be power of two
* @return aligned value
*/
public static int align(int v, int a) {
return (v + a - 1) & -a;
}

public static long align(long addr, int align) {
if ((addr % align) == 0) {
return addr;
} else {
return ((addr / align) + 1) * align;
}
/**
* Aligns the argument to the given alignment.
* Alignment should be a power of two.
*
* @param v value to align
* @param a alignment, should be power of two
* @return aligned value
*/
public static long align(long v, int a) {
return (v + a - 1) & -a;
}
}
60 changes: 60 additions & 0 deletions jol-core/src/test/java/org/openjdk/jol/util/MathUtilTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package org.openjdk.jol.util;

import org.junit.Assert;
import org.junit.Test;

public class MathUtilTest {

static int slowIntAlign(int v, int a) {
if (v % a == 0) {
return v;
} else {
return ((v / a) + 1) * a;
}
}

static long slowLongAlign(long v, int a) {
if (v % a == 0) {
return v;
} else {
return ((v / a) + 1) * a;
}
}

@Test
public void alignIntTest() {
Assert.assertEquals(0, MathUtil.align(0, 2));
Assert.assertEquals(2, MathUtil.align(1, 2));
Assert.assertEquals(2, MathUtil.align(2, 2));
Assert.assertEquals(4, MathUtil.align(3, 2));
Assert.assertEquals(4, MathUtil.align(4, 2));

for (int v = 0; v < 10; v++) {
for (int a = 1; a <= 256; a *= 2) {
Assert.assertEquals(slowIntAlign(v, a), MathUtil.align(v, a));
}
}
}

@Test
public void alignLongTest() {
Assert.assertEquals(0, MathUtil.align(0L, 2));
Assert.assertEquals(2, MathUtil.align(1L, 2));
Assert.assertEquals(2, MathUtil.align(2L, 2));
Assert.assertEquals(4, MathUtil.align(3L, 2));
Assert.assertEquals(4, MathUtil.align(4L, 2));

for (long v = 0; v < 10; v++) {
for (int a = 1; a <= 256; a *= 2) {
Assert.assertEquals(slowLongAlign(v, a), MathUtil.align(v, a));
}
}

for (long v = Integer.MAX_VALUE; v < Integer.MAX_VALUE + 10L; v++) {
for (int a = 1; a <= 256; a *= 2) {
Assert.assertEquals(slowLongAlign(v, a), MathUtil.align(v, a));
}
}
}

}

0 comments on commit c47d165

Please sign in to comment.