Skip to content

Commit

Permalink
improved parseDouble & parseFloat perforamnce
Browse files Browse the repository at this point in the history
  • Loading branch information
wenshao committed May 3, 2019
1 parent b5777ae commit 339fbe0
Show file tree
Hide file tree
Showing 4 changed files with 325 additions and 1 deletion.
Expand Up @@ -1359,13 +1359,31 @@ public Object createInstance(Map<String, Object> map, ParserConfig config) //
if (value instanceof Number) {
field.setFloat(object, ((Number) value).floatValue());
continue;
} else if (value instanceof String) {
String strVal = (String) value;
float floatValue;
if (strVal.length() <= 10) {
floatValue = TypeUtils.parseFloat(strVal);
} else {
floatValue = Float.parseFloat(strVal);
}

field.setFloat(object, floatValue);
continue;
}
} else if (paramType == double.class) {
if (value instanceof Number) {
field.setDouble(object, ((Number) value).doubleValue());
continue;
} else if (value instanceof String) {
double doubleValue = Double.parseDouble((String) value);
String strVal = (String) value;
double doubleValue;
if (strVal.length() <= 10) {
doubleValue = TypeUtils.parseDouble(strVal);
} else {
doubleValue = Double.parseDouble(strVal);
}

field.setDouble(object, doubleValue);
continue;
}
Expand Down
126 changes: 126 additions & 0 deletions src/main/java/com/alibaba/fastjson/util/TypeUtils.java
Expand Up @@ -2618,6 +2618,132 @@ public static boolean isHibernateInitialized(Object object){
return true;
}

public static double parseDouble(String str) {
final int len = str.length();
if (len > 10) {
return Double.parseDouble(str);
}

boolean negative = false;

long longValue = 0;
int scale = 0;
for (int i = 0; i < len; ++i) {
char ch = str.charAt(i);
if (ch == '-' && i == 0) {
negative = true;
continue;
}

if (ch == '.') {
if (scale != 0) {
return Double.parseDouble(str);
}
scale = len - i - 1;
continue;
}

if (ch >= '0' && ch <= '9') {
int digit = ch - '0';
longValue = longValue * 10 + digit;
} else {
return Double.parseDouble(str);
}
}

if (negative) {
longValue = -longValue;
}

switch (scale) {
case 0:
return (double) longValue;
case 1:
return ((double) longValue) / 10;
case 2:
return ((double) longValue) / 100;
case 3:
return ((double) longValue) / 1000;
case 4:
return ((double) longValue) / 10000;
case 5:
return ((double) longValue) / 100000;
case 6:
return ((double) longValue) / 1000000;
case 7:
return ((double) longValue) / 10000000;
case 8:
return ((double) longValue) / 100000000;
case 9:
return ((double) longValue) / 1000000000;
}

return Double.parseDouble(str);
}

public static float parseFloat(String str) {
final int len = str.length();
if (len >= 10) {
return Float.parseFloat(str);
}

boolean negative = false;

long longValue = 0;
int scale = 0;
for (int i = 0; i < len; ++i) {
char ch = str.charAt(i);
if (ch == '-' && i == 0) {
negative = true;
continue;
}

if (ch == '.') {
if (scale != 0) {
return Float.parseFloat(str);
}
scale = len - i - 1;
continue;
}

if (ch >= '0' && ch <= '9') {
int digit = ch - '0';
longValue = longValue * 10 + digit;
} else {
return Float.parseFloat(str);
}
}

if (negative) {
longValue = -longValue;
}

switch (scale) {
case 0:
return (float) longValue;
case 1:
return ((float) longValue) / 10;
case 2:
return ((float) longValue) / 100;
case 3:
return ((float) longValue) / 1000;
case 4:
return ((float) longValue) / 10000;
case 5:
return ((float) longValue) / 100000;
case 6:
return ((float) longValue) / 1000000;
case 7:
return ((float) longValue) / 10000000;
case 8:
return ((float) longValue) / 100000000;
case 9:
return ((float) longValue) / 1000000000;
}

return Float.parseFloat(str);
}

public static long fnv1a_64_lower(String key){
long hashCode = 0xcbf29ce484222325L;
for(int i = 0; i < key.length(); ++i){
Expand Down
@@ -0,0 +1,95 @@
package com.alibaba.json.bvt.parser;

import com.alibaba.fastjson.util.TypeUtils;
import junit.framework.TestCase;

import java.util.Random;

public class TypeUtils_parseDouble_Test extends TestCase {
public void test_0() throws Exception {
Random r = new Random();

for (int i = 0; i < 1000 * 1000; ++i) {
String str = Float.toString(r.nextFloat());
assertEquals(Double.parseDouble(str), TypeUtils.parseDouble(str));
}
}

public void test_0_d() throws Exception {
Random r = new Random();

for (int i = 0; i < 1000 * 1000; ++i) {
String str = Double.toString(r.nextDouble());
assertEquals(Double.parseDouble(str), TypeUtils.parseDouble(str));
}
}


public void test_1() throws Exception {
Random r = new Random();

for (int i = 0; i < 1000 * 1000; ++i) {
String str = Integer.toString(r.nextInt());
assertEquals(Double.parseDouble(str), TypeUtils.parseDouble(str));
}
}

public void test_2() throws Exception {
Random r = new Random();

for (int i = 0; i < 1000 * 1000; ++i) {
String str = Integer.toString(r.nextInt(1000000000));
assertEquals(Double.parseDouble(str), TypeUtils.parseDouble(str));
}
}

public void test_3() throws Exception {
Random r = new Random();

for (int i = 0; i < 1000 * 1000; ++i) {
String str = Long.toString(r.nextLong());
assertEquals(Double.parseDouble(str), TypeUtils.parseDouble(str));
}
}

public void test_4() throws Exception {
String[] array = new String[] {
"0.34856254",
"1",
"12",
"123",
"1234",
"12345",
"123456",
"1234567",
"12345678",
"123456789",
"1234567890",
".1"
,"1.1"
,"12.1"
, "123.1"
, "1234.1"
, "12345.1"
, "123456.1"
, "1234567.1"
, "12345678.1"
, "0.1"
, "0.12"
, "0.123"
, "0.1234"
, "0.12345"
, "0.123456"
, "0.1234567"
, "0.12345678"
, "0.123456789"
, "0.1234567891"
, "0.12345678901"
, "0.123456789012"
};

for (String str : array) {
assertEquals(Double.parseDouble(str), TypeUtils.parseDouble(str));
}
}
}
@@ -0,0 +1,85 @@
package com.alibaba.json.bvt.parser;

import com.alibaba.fastjson.util.TypeUtils;
import junit.framework.TestCase;

import java.util.Random;

public class TypeUtils_parseFloat_Test extends TestCase {
public void test_0() throws Exception {
Random r = new Random();

for (int i = 0; i < 1000 * 1000; ++i) {
String str = Float.toString(r.nextFloat());
assertEquals(Float.parseFloat(str), TypeUtils.parseFloat(str));
}
}

public void test_1() throws Exception {
Random r = new Random();

for (int i = 0; i < 1000 * 1000; ++i) {
String str = Integer.toString(r.nextInt());
assertEquals(Float.parseFloat(str), TypeUtils.parseFloat(str));
}
}

public void test_2() throws Exception {
Random r = new Random();

for (int i = 0; i < 1000 * 1000; ++i) {
String str = Integer.toString(r.nextInt(1000000000));
assertEquals(Float.parseFloat(str), TypeUtils.parseFloat(str));
}
}

public void test_3() throws Exception {
Random r = new Random();

for (int i = 0; i < 1000 * 1000; ++i) {
String str = Long.toString(r.nextLong());
assertEquals(Float.parseFloat(str), TypeUtils.parseFloat(str));
}
}

public void test_4() throws Exception {
String[] array = new String[] {
"0.34856254",
"1",
"12",
"123",
"1234",
"12345",
"123456",
"1234567",
"12345678",
"123456789",
"1234567890",
".1"
,"1.1"
,"12.1"
, "123.1"
, "1234.1"
, "12345.1"
, "123456.1"
, "1234567.1"
, "12345678.1"
, "0.1"
, "0.12"
, "0.123"
, "0.1234"
, "0.12345"
, "0.123456"
, "0.1234567"
, "0.12345678"
, "0.123456789"
, "0.1234567891"
, "0.12345678901"
, "0.123456789012"
};

for (String str : array) {
assertEquals(Float.parseFloat(str), TypeUtils.parseFloat(str));
}
}
}

0 comments on commit 339fbe0

Please sign in to comment.