Gross Lack of efficacy in using LambdaJ over iteration
Asked Answered
A

2

0

In a java ee application with JSF and JPA,I have to calculate totals of attributes in lists of objects. I have used LambdaJ library to achieve the calculation of sums.

As I use this sort of summations in several places of the application with possible implications to the overall performance, I designed the following test java application to test the efficacy of LambdaJ.

This application demonstrated a gross lack of efficacy of LambdaJ.

Is there any error in the testing programme or should I replace all lambdaJ occurrences with iterations ?

The result

Time taken to calculate a single total by iteration is 15 milliseconds.
Time taken to calculate a single total by LambdaJ is 199 milliseconds.
Time taken to calculate multiple totals by iteration is 23 milliseconds.
Time taken to calculate multiple totals by LambdaJ is 114 milliseconds.

The Main Method

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package com.lakmedi;

import ch.lambdaj.Lambda;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;

/**
 *
 * @author buddhika
 */
public class main {

    public static void main(String[] args) {
        List<Bill> bills = new ArrayList<>();
        Random r = new Random();
        for (int i = 0; i < 100000; i++) {
            Bill b = new Bill();
            b.setGrossTotal(r.nextDouble());
            b.setDiscount(r.nextDouble());
            b.setNetTotal(b.getGrossTotal() - b.getDiscount());
            bills.add(b);
        }
        calSingleByIteration(bills);
        calSingleByLambdja(bills);
        calMultipleByIteration(bills);
        calMultipleByLambdja(bills);
    }

    public static void calSingleByIteration(List<Bill> bills) {
        Date startTime = new Date();
        double grossTotal = 0.0;
        for (Bill b : bills) {
            grossTotal += b.getGrossTotal();
        }
        Date endTime = new Date();
        long timeTaken = endTime.getTime() - startTime.getTime();
        System.out.println("Time taken to calculate a single total by iteration is " + timeTaken + " milliseconds.");
    }

    public static void calSingleByLambdja(List<Bill> bills) {
        Date startTime = new Date();
        double grossTotal = Lambda.sumFrom(bills).getGrossTotal();
        Date endTime = new Date();
        long timeTaken = endTime.getTime() - startTime.getTime();
        System.out.println("Time taken to calculate a single total by LambdaJ is " + timeTaken + " milliseconds.");
    }

    public static void calMultipleByIteration(List<Bill> bills) {
        Date startTime = new Date();
        double grossTotal = 0.0;
        double discount = 0.0;
        double netTotal = 0.0;
        for (Bill b : bills) {
            grossTotal += b.getGrossTotal();
            discount += b.getDiscount();
            netTotal += b.getNetTotal();
        }
        Date endTime = new Date();
        long timeTaken = endTime.getTime() - startTime.getTime();
        System.out.println("Time taken to calculate multiple totals by iteration is " + timeTaken + " milliseconds.");
    }

    public static void calMultipleByLambdja(List<Bill> bills) {
        Date startTime = new Date();
        double grossTotal = Lambda.sumFrom(bills).getGrossTotal();
        double discount = Lambda.sumFrom(bills).getDiscount();
        double netTotal = Lambda.sumFrom(bills).getNetTotal();
        Date endTime = new Date();
        long timeTaken = endTime.getTime() - startTime.getTime();
        System.out.println("Time taken to calculate multiple totals by LambdaJ is " + timeTaken + " milliseconds.");
    }

}

The Bill Class

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package com.lakmedi;

/**
 *
 * @author buddhika
 */
public class Bill {
    private double grossTotal;
    private double netTotal;
    private double discount;

    public double getGrossTotal() {
        return grossTotal;
    }

    public void setGrossTotal(double grossTotal) {
        this.grossTotal = grossTotal;
    }

    public double getNetTotal() {
        return netTotal;
    }

    public void setNetTotal(double netTotal) {
        this.netTotal = netTotal;
    }

    public double getDiscount() {
        return discount;
    }

    public void setDiscount(double discount) {
        this.discount = discount;
    }


}
Annelleannemarie answered 16/8, 2014 at 20:54 Comment(1)
I think you mean efficiency rather than efficacy, because lambdaj is producing the expected results, it's just slower than you expect.Hearty
S
3

Assuming you mean efficiency and not efficacy, then your measured performance is more or less as expected - see LambdaJ's own performance analysis.

You might get better results using Java 8 Lambda Expressions, but the main goal here is to improve readability and maintainability of source code and not speed. Are you sure that the time needed for performing the summations is critical to the overall performance of the application? I doubt it considering (I/O) waiting times for HTTP-traffic (JSF) and database queries (JPA) in which case this is premature optimization (the root of all evil).

Sequela answered 17/8, 2014 at 0:8 Comment(0)
H
2

Firstly, check you are using the latest version of LambdaJ, because the project site indicates that recent versions have some performance improvements.

However, I think you should expect lambdaj to be slower than writing the equivalent for-loop. Behind the more concise syntax, the JVM is doing a lot more work.

You could consider dropping lambdaj and using Java 8 streams and lambda expressions.

Here's what the author of lambdaj has to say on the matter:

Lemme clarify this once again: after the release of Java8 I don't see any point in developing/maintaining #lambdaj. Move to Java8 & be happy

-- Mario Fusco, May 2014

Hearty answered 17/8, 2014 at 0:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.