Code Monkey home page Code Monkey logo

Comments (19)

Antibrumm avatar Antibrumm commented on August 29, 2024

Thanks for the hint. I wrote that part of the readme without actually testing it.
I have now added the code of the Jackson2Helper to the project itself. It uses now a copy of the objectMapper for each writeFiltered operation.

I hope this solves it for you. Let me know :)

from jackson-antpathfilter.

Antibrumm avatar Antibrumm commented on August 29, 2024

I have just added a ConcurrencyTest to prove that this is working.

from jackson-antpathfilter.

krishna81m avatar krishna81m commented on August 29, 2024

Is there any efficient way of reusing the same object mapper? I know you
can get the writer, reader instances by filter using
mapper.getwriter(filter) and cache them by filter id or class?
Just an idea.
On Oct 27, 2015 9:23 AM, "Antibrumm" [email protected] wrote:

I have just added a ConcurrencyTest to prove that this is working.


Reply to this email directly or view it on GitHub
#4 (comment)
.

from jackson-antpathfilter.

Antibrumm avatar Antibrumm commented on August 29, 2024

you can always keep a reference from the objectMapper with the Filter X and reuse it.

I use the code of v1.0.0 in a productive AngularJS + Spring project myself and i did not have to bother about this kind of performance issues (yet). I'm just using the call to Jackson2Helper.writeFiltered()

from jackson-antpathfilter.

krishna81m avatar krishna81m commented on August 29, 2024

I remember doing some benchmarks with a well configured mapper/writer with
a few custom modules and noticed at least 10%-20% increase in through put.

Even the Jackson page highly recommends reusing.
On Oct 27, 2015 9:35 AM, "Antibrumm" [email protected] wrote:

you can always keep a reference from the objectMapper with the Filter X
and reuse it.

I use the code of v1.0.0 in a productive AngularJS + Spring project myself
and i did not have to bother about this kind of performance issues. I'm
just using the call to Jackson2Helper.writeFiltered()


Reply to this email directly or view it on GitHub
#4 (comment)
.

from jackson-antpathfilter.

Antibrumm avatar Antibrumm commented on August 29, 2024

That might absolutely be the case. The thing I wanted to say, is just, that writing out the JSON string itself was not yet the bottleneck for me. Times for Authentication/Authorization, Template rendering and querying the database for some data was always more important to invest some time in it.

One would also have to consider the memory footprint with caching each of the ObjectMappers.

That said there is already the possibility to do this on your side. This way you can also decide if you want to cache each and every ObjectMapper or just some that are heavily used within your system.

Jackson2Helper contains already a method to get the configured object mapper:
public ObjectMapper buildObjectMapper(final String... filters) {...}

Instead of calling writeFiltered you might call this and fill a cache on your side.

I did a quick benchmark based on JMH and for now i did not get very big differences at all. But I am a complete newbie about microbenchmarks :)

Benchmark Mode Cnt Score Error Units
FilterBenchmark.measureCached avgt 25 205.334 4.693 ms/op
FilterBenchmark.measureNotCached avgt 25 208.020 6.377 ms/op
private final Map<Integer, ObjectMapper> cache = new ConcurrentHashMap<Integer, ObjectMapper>();

public String writeCachedFiltered(final Object value, final String... filters) {
    try {
        int key = Arrays.hashCode(filters);
        if (!cache.containsKey(key)) {
            cache.put(key, buildObjectMapper(filters));
        }
        return cache.get(key).writeValueAsString(value);
    } catch (IOException ioe) {
        throw new RuntimeException("Could not write object filtered.", ioe);
    }
}

from jackson-antpathfilter.

Antibrumm avatar Antibrumm commented on August 29, 2024

I found a nice way to include JMH into the build process as a separate profile. Please feel free to play with it. It will be pushed soon.

from jackson-antpathfilter.

Antibrumm avatar Antibrumm commented on August 29, 2024

The setup of JMH is now included as a maven profile -Pbenchmark
see commit f8f239d

from jackson-antpathfilter.

krishna81m avatar krishna81m commented on August 29, 2024

Great, maybe, because mapper does not have additional modules. I vaguely remember ObjectMappers are also heavy so they could add to GC, wonder how much size is occupied by a single instance.

How long was the benchmark run?

from jackson-antpathfilter.

krishna81m avatar krishna81m commented on August 29, 2024

Was testing your filter using Spring 4.2 filter support https://jira.spring.io/browse/SPR-12586
Rest application and found that it is not compatible with MappingJacksonValue. When debugging, I did notice that jackson BeanSerializerBase class was only pass the parent each object property but not setting the propertyFilterId for serializing these child properties.

Custom mapper and controller class:

objectMapper.addMixIn(Object.class, AntPathFilterMixin.class);

public @ResponseBody MappingJacksonValue jsonFilter() {
        MappingJacksonValue jacksonValue = new MappingJacksonValue(new ParentObj());
        jacksonValue.setFilters(
                    new SimpleFilterProvider()
            .addFilter("1",
                    new AntPathPropertyFilter("nestedObj", "nestedObj.nestedProperty")
            );
                );
        return jacksonValue;
    }

com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFieldsFiltered(Object, JsonGenerator, SerializerProvider)
code sets _propertyFilterId="antPathFilter" only on the current object but not on the child objects which therefore does not filter nested properties as filters are not used in nested object serialization.

int i = 0;
        try {
            for (final int len = props.length; i < len; ++i) {
                BeanPropertyWriter prop = props[i];
                if (prop != null) { // can have nulls in filtered list
                    filter.serializeAsField(bean, jgen, provider, prop);
                }
            }
            if (_anyGetterWriter != null) {
                _anyGetterWriter.getAndFilter(bean, jgen, provider, filter);
            }

The fix for this solution was to explicitly add the same @jsonfilter("antPathFilter") on all classes that are being nested, which did not make any sense to me. What if I wanted to support multiple filters at the same time tomorrow?

from jackson-antpathfilter.

Antibrumm avatar Antibrumm commented on August 29, 2024

I will have to check this out. This is where the Mixin feature of jackson is very handy. You can define filters for each object type on the side without touching the DTOs. I think we should open another issue for that one.

from jackson-antpathfilter.

Antibrumm avatar Antibrumm commented on August 29, 2024

I don't use Spring 4.2 yet but have you defined the MixIn on the ObjectMapper within MappingJackson2HttpMessageConverter ?
The problem I would see here is that you would now always use the MixIn on each json convertion. I'm not aware of the possibility to define two MappingJackson2HttpMessageConverter and as far as I know you can only declare one MixIn per class.

from jackson-antpathfilter.

krishna81m avatar krishna81m commented on August 29, 2024

Yes of course, I setup a custom mapper with the mixin

        content-negotiation-manager="contentNegotiationManager">
            <mvc:message-converters register-defaults="false">
                <bean class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
                    <property name="objectMapper" ref="customObjectMapper"/>
                </bean>
                <bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter"/>
                <bean class="org.springframework.http.converter.xml.SourceHttpMessageConverter"/>
                <bean class="org.springframework.http.converter.FormHttpMessageConverter"/>
                <bean class="org.springframework.http.converter.StringHttpMessageConverter"/>
            </mvc:message-converters>
    </mvc:annotation-driven>

<bean id="customObjectMapper" 

.. objectMapper.addMixIn(Object.class, AntPathFilterMixin.class);

It did not work for nested property filtering for the above mentioned reason.

from jackson-antpathfilter.

Antibrumm avatar Antibrumm commented on August 29, 2024

I have just updated the readme with an approach for MappingJacksonValue that works for me in one of our applications. I think your only issue is that you gave a wrong name in the addFilter method:

    new SimpleFilterProvider()
            .addFilter("1",   // <-- this needs to be "antPathFilter"
                    new AntPathPropertyFilter("nestedObj", "nestedObj.nestedProperty");

from jackson-antpathfilter.

krishna81m avatar krishna81m commented on August 29, 2024

Just checked, did give the right filter name "antPathFilter", probably, accidentally removed the name while commenting on ticket.

As I mentioned above, this does work, but the problem is setting the filter on all entities.
"The fix for this solution was to explicitly add the same @jsonfilter("antPathFilter") on all classes that are being nested, which did not make any sense to me. What if I wanted to support multiple filters at the same time tomorrow?"

from jackson-antpathfilter.

krishna81m avatar krishna81m commented on August 29, 2024

Doing some benchmarks on a complex object and found that throughput with filter is small. This is not a valid comparison as I could not yet figure out how to specify nested property filter in any other way, but it is still quite slow.

                                threads     throughput
AntMatcher                 10                  25
SimpleProp                 10                  300                 
(no nested prop filtering) 

from jackson-antpathfilter.

Antibrumm avatar Antibrumm commented on August 29, 2024

Which version did you use. Already 1.0.1 with the cached filter results for lists?

from jackson-antpathfilter.

Antibrumm avatar Antibrumm commented on August 29, 2024

I know there is still some improvement possible during the pathToTest creation. But the AntPath implementation is pretty heavy. It's just a copy out of Spring.

from jackson-antpathfilter.

Antibrumm avatar Antibrumm commented on August 29, 2024

Let's continue this in another issue i have created for performance: #5

from jackson-antpathfilter.

Related Issues (12)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.