Last active
September 20, 2017 02:51
-
-
Save varren/3b7468a1d7abadad4958fe6bd7d42d44 to your computer and use it in GitHub Desktop.
Jackson performance Tests
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import com.fasterxml.jackson.annotation.JsonFormat; | |
import com.fasterxml.jackson.annotation.JsonIgnore; | |
import com.fasterxml.jackson.annotation.JsonProperty; | |
import com.fasterxml.jackson.core.JsonFactory; | |
import com.fasterxml.jackson.core.JsonParser; | |
import com.fasterxml.jackson.core.JsonProcessingException; | |
import com.fasterxml.jackson.core.JsonToken; | |
import com.fasterxml.jackson.core.type.TypeReference; | |
import com.fasterxml.jackson.databind.DeserializationContext; | |
import com.fasterxml.jackson.databind.JsonDeserializer; | |
import com.fasterxml.jackson.databind.ObjectMapper; | |
import com.fasterxml.jackson.databind.module.SimpleModule; | |
import java.io.IOException; | |
import java.util.*; | |
public class Main { | |
public static String json = "{\"d\": {\"results\": [{\"name\":\"one\"},{\"name\":\"two\"}]}}"; | |
public static ObjectMapper mapper = new ObjectMapper(); | |
public static class User { | |
public String name; | |
@Override | |
public String toString() { | |
return "User{name='" + name + "'}"; | |
} | |
} | |
static class Data { | |
@JsonProperty("d") | |
public Results d; | |
} | |
static class Results { | |
@JsonProperty("results") | |
public List<User> results; | |
} | |
static class MyList extends ArrayList<User> { | |
@JsonIgnore | |
@Override | |
public boolean isEmpty() { | |
return super.isEmpty(); | |
} | |
} | |
public static void main(String[] args) throws IOException { | |
/********************* TEST1 ****************************/ | |
test(() -> { | |
Data data = mapper.readerFor(new TypeReference<Data>() { | |
}).readValue(json); | |
Results result =data.d; | |
List<User> users = result.results; | |
},"readerFor()"); | |
/********************* TEST2 ****************************/ | |
test(() -> { | |
Results result = mapper.readerFor(new TypeReference<Results>() { | |
}).withRootName("d").readValue(json); | |
List<User> users = result.results; | |
},"readerFor().withRootName"); | |
/********************* TEST3 ****************************/ | |
test(() -> { | |
List<User> users = mapper.readerFor( | |
new TypeReference<List<User>>() { | |
}).readValue(mapper.readTree(json).get("d").get("results")); | |
},"readerFor().readValue(readTree)"); | |
/********************* TEST4 ****************************/ | |
test(() -> { | |
List<User> users = mapper.convertValue( | |
mapper.readTree(json).get("d").get("results"), | |
new TypeReference<List<User>>() { | |
}); | |
},"convertValue(readTree)"); | |
/********************* TEST5 ****************************/ | |
JsonFactory jsonFactory = new JsonFactory(); | |
jsonFactory.setCodec(mapper); | |
test(() -> { | |
List<User> array = new ArrayList<>(); | |
JsonParser p = jsonFactory.createParser(json); | |
JsonToken curr; | |
while((curr = p.nextToken()) != null) | |
//this is just hardcoded version, usually you check for every tocken and act accordingly | |
//we just need to find array | |
if (curr == JsonToken.START_ARRAY){ | |
while(p.nextToken() != JsonToken.END_ARRAY){ | |
array.add(p.readValueAs(User.class)); | |
} | |
} | |
},"custom inplace parser"); | |
/********************* TEST6 ****************************/ | |
//some setup needed for custom deserializer | |
SimpleModule module = new SimpleModule(); | |
module.addDeserializer(MyList.class, new MyObjectDeserializer()); | |
mapper.registerModule(module); | |
test(() -> { | |
List<User> users = mapper.readValue(json, MyList.class); | |
},"custom deserializer"); | |
} | |
public static class MyObjectDeserializer extends JsonDeserializer<MyList>{ | |
@Override | |
public MyList deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException { | |
JsonToken curr; | |
MyList array = new MyList(); | |
while((curr = p.nextToken()) != null) | |
//this is just hardcoded version, usually you check for every tocken and act accordingly | |
//we just need to find array | |
if (curr == JsonToken.START_ARRAY){ | |
while(p.nextToken() != JsonToken.END_ARRAY){ | |
array.add(p.readValueAs(User.class)); | |
} | |
} | |
return array; | |
} | |
} | |
public interface Test { | |
void run() throws Exception; | |
} | |
public static void test(Test runnable, String testName) { | |
Runtime runtime = Runtime.getRuntime(); | |
runtime.gc(); | |
long startTime = System.currentTimeMillis(); | |
try { | |
for (int i = 0; i < 10000000; i++) | |
runnable.run(); | |
} catch (Exception e) { | |
e.printStackTrace(); | |
} | |
long endTime = System.currentTimeMillis(); | |
long totalTime = endTime - startTime; | |
System.out.println(testName + ": " +totalTime); | |
} | |
} | |
/* | |
Using 100000000 itterations | |
Results for simple json: "{"d": {"results": [{"name":"one"},{"name":"two"}]}}" | |
readerFor(): 53392 <= 2 root util objects | |
readerFor().withRootName: 55311 <= 1 root util object and withRootName option | |
readerFor().readValue(readTree): 113899 | |
convertValue(readTree): 115614 | |
custom inplace parser: 53194 <= JsonParser(same code as in custom deserializer) | |
custom deserializer: 56032 | |
Using 1000000 itterations | |
For 5 huge users ( demo at the bottom of the page, 40-50 lines of json each, 6k lines total): | |
readerFor(): 26555 | |
readerFor().withRootName: 25877 | |
readerFor().readValue(readTree): 39733 | |
convertValue(readTree): 41539 | |
custom inplace parser: 28324 | |
custom deserializer: 29000 | |
Using 100000 itterations | |
For 100+ huge users ( demo at the bottom of the page, 40-50 lines of json each): | |
readerFor(): 64383 | |
readerFor().withRootName: 63325 | |
readerFor().readValue(readTree): 92239 | |
convertValue(readTree): 99307 | |
custom inplace parser: 69633 | |
custom deserializer: 70230 | |
Huge user demo is generated with https://www.json-generator.com/ looks like this: | |
{ | |
"_id": "59c1c1eaecf0ac7a6fd552de", | |
"index": 0, | |
"guid": "6dc6ba8f-01c1-4669-a6a2-035b1240fba2", | |
"isActive": true, | |
"balance": "$1,442.02", | |
"picture": "http://placehold.it/32x32", | |
"age": 28, | |
"eyeColor": "green", | |
"name": "Charmaine Sears", | |
"gender": "female", | |
"company": "BESTO", | |
"email": "[email protected]", | |
"phone": "+1 (903) 572-3249", | |
"address": "792 Harwood Place, Corinne, West Virginia, 1146", | |
"about": "Excepteur cupidatat velit duis enim irure amet. Commodo culpa nostrud eiusmod incididunt aliqua ut et adipisicing laborum et laborum. Irure non non esse amet exercitation deserunt Lorem mollit aliqua esse.\r\n", | |
"registered": "2015-03-19T08:06:51 -03:00", | |
"latitude": -55.062389, | |
"longitude": -27.841253, | |
"tags": [ | |
"duis", | |
"aliquip", | |
"tempor", | |
"ad", | |
"voluptate", | |
"magna", | |
"eu" | |
], | |
"friends": [ | |
{ | |
"id": 0, | |
"name": "Nichole Sanford" | |
}, | |
{ | |
"id": 1, | |
"name": "Bray Short" | |
}, | |
{ | |
"id": 2, | |
"name": "Williams Kent" | |
} | |
], | |
"greeting": "Hello, Charmaine Sears! You have 7 unread messages.", | |
"favoriteFruit": "banana" | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Memory tests: https://i.stack.imgur.com/bftGe.png
3 and 4 tests almost 2 times more memory then 1, 2, 4 ,5