Link to home
Start Free TrialLog in
Avatar of Paiano_luca
Paiano_luca

asked on

printf performancy

hello, im new to java and im struggling with the performance of a small prog.

I'm working with 2 arrays and 1 for loop(measured time 0ms) and a method with 2 for loops in wich i printf the data in those arrays(measured time 20 ms). It should be running at 12 ms tops, but i cant find a shorter nor faster way to write my code.

any help is appreciated
Avatar of CEHJ
CEHJ
Flag of United Kingdom of Great Britain and Northern Ireland image

Please post the code
Avatar of Paiano_luca
Paiano_luca

ASKER

		int jaarlijksGespaard = 0;
		float rentevoet = 0.0f;
		float[] gespaardBedrag= new float[21];
		float[] jaarKapitaal = new float[21];
		float[] interesten = new float[21];
		Scanner input = new Scanner(System.in);

		// vraag maandbedrag op, deze mag geen 0 zijn
		while (jaarlijksGespaard <= 0) {
			System.out.print("Geef het maandbedrag in: ");
			jaarlijksGespaard = (input.nextInt()*12);
		}
		// vraag rentevoet op, deze mag geen 0 zijn
		while (rentevoet <= 0) {
			System.out.print("Geef uw rentevoet in: ");
			rentevoet = (input.nextFloat() / 100);
		}

        
		// jaarlijksGespaard uitprinten
		System.out.println("Het jaarlijks te sparen bedrag is " + jaarlijksGespaard + " euro.\n");

		// var. gespaardBedrag aangemaakt en gelijkgesteld aan jaarlijksGespaard
		// om het vaste jaarlijks gespaard bedrag te behouden & om alle
		// gespaarde bedragen bij te houden.
		
		// berekening van het gespaard bedrag, interesten en het kapitaal per
		// jaar + het uitprinten hiervan 
		for (int i = 0; i < jaarKapitaal.length; i++) {
			if(i ==0){
			gespaardBedrag[i] = jaarKapitaal[i] + jaarlijksGespaard;
			}else{
				gespaardBedrag[i] = jaarKapitaal[i-1] + jaarlijksGespaard;
			}
			interesten[i] = gespaardBedrag[i] * rentevoet;
			jaarKapitaal[i] = gespaardBedrag[i] + interesten[i];
			// gespaardBedrag = gespaarde bedrag + de verworven intersten + de
			// nieuw gespaarde 3000€
		}
		
		// afprinten van alle bedragen per jaar via de methode druk(...)
		druk(jaarKapitaal, interesten, gespaardBedrag);
		
		input.close();
	}

	private static void druk(float[] kapitaal, float[] interesten, float[] gespaardBedrag) {
		

		long startTime = System.nanoTime();
		// titels uitprinten
		System.out.printf("Per gespaard jaar:%n%-15s %-20s %-15s %-15s %n", "Jaar", "Gespaard Bedrag", "Interesten", "Totaal tegoed");
		
		for (int i = 0; i < kapitaal.length; i ++) {
		// uitprinten van het gevraagde met de juiste formats

		System.out.printf("na %d jaar\t%-20.2f %-15.2f %-10.2f %n", i+1, gespaardBedrag[i], interesten[i],	kapitaal[i]);
		}		
		// printen van de titels van de per 2 gespaarde jaren
		System.out.printf("%n Per gespaarde jaren: %n %-15s %-20s %-15s %-15s %n", "Jaar", "Gespaard Bedrag",
				"Interesten", "Totaal tegoed");
		
		for (int i = 1; i < kapitaal.length; i +=2) {
		// uitprinten van het gevraagde met de juiste formats
		System.out.printf("na %d jaar\t%-20.2f %-15.2f %-10.2f %n", i + 1, gespaardBedrag[i], interesten[i], kapitaal[i]);
		}

        long difference = System.nanoTime() - startTime;
        System.out.println("\nTotal execution time: " + String.format("%d ms", TimeUnit.NANOSECONDS.toMillis(difference)));
	}

Open in new window


this is the output:

Geef het maandbedrag in: 250
Geef uw rentevoet in: 2,5
Het jaarlijks te sparen bedrag is 3000 euro.

Per gespaard jaar:
Jaar            Gespaard Bedrag      Interesten      Totaal tegoed  
na 1 jaar      3000,00              75,00           3075,00    
na 2 jaar      6075,00              151,88          6226,88    
na 3 jaar      9226,88              230,67          9457,55    
na 4 jaar      12457,55             311,44          12768,99  
na 5 jaar      15768,99             394,22          16163,21  
na 6 jaar      19163,21             479,08          19642,29  
na 7 jaar      22642,29             566,06          23208,35  
na 8 jaar      26208,35             655,21          26863,56  
na 9 jaar      29863,56             746,59          30610,15  
na 10 jaar      33610,15             840,25          34450,40  
na 11 jaar      37450,40             936,26          38386,66  
na 12 jaar      41386,66             1034,67         42421,33  
na 13 jaar      45421,33             1135,53         46556,87  
na 14 jaar      49556,87             1238,92         50795,79  
na 15 jaar      53795,79             1344,89         55140,68  
na 16 jaar      58140,68             1453,52         59594,20  
na 17 jaar      62594,20             1564,85         64159,05  
na 18 jaar      67159,05             1678,98         68838,03  
na 19 jaar      71838,03             1795,95         73633,98  
na 20 jaar      76633,98             1915,85         78549,84  
na 21 jaar      81549,84             2038,75         83588,58  

 Per gespaarde jaren:
 Jaar            Gespaard Bedrag      Interesten      Totaal tegoed  
na 2 jaar      6075,00              151,88          6226,88    
na 4 jaar      12457,55             311,44          12768,99  
na 6 jaar      19163,21             479,08          19642,29  
na 8 jaar      26208,35             655,21          26863,56  
na 10 jaar      33610,15             840,25          34450,40  
na 12 jaar      41386,66             1034,67         42421,33  
na 14 jaar      49556,87             1238,92         50795,79  
na 16 jaar      58140,68             1453,52         59594,20  
na 18 jaar      67159,05             1678,98         68838,03  
na 20 jaar      76633,98             1915,85         78549,84  

Total execution time: 18 ms
Your code is difficult to read - and not just because it's in Dutch. Data that belong together should be encapsulated together in one class, not in parallel arrays. It's really pointless learning/doing Java if you're going to avoid using it in an object-oriented way.

At this stage, you really shouldn't concern yourself with the performancy of  printf. Your performance issues are far more likely to stem from inefficient looping, so you need to check all of that
thank you, im going to try to follow your advice
English might have helped since all of us know English.

Are the print statements supposed to be included in the timing? If so, can you put them in another thread while doing other work?

Check your memory layout and usage. Try to keep your cache lines hot.

Take advantage of prefeching. Sometimes to do that, you may have to break a class up into arrays depending upon how you access the data. But the results can be significant.
ASKER CERTIFIED SOLUTION
Avatar of dpearson
dpearson

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
thank you for all the advises, i have to go with dpearson's advice. im still a fresh starter with java(1 month) and this is the most helpfull answer! thank you all for contributing in helping
After making the changes, how long did it take?
Sounds like a good course. Could you let others know where to sign up?
Since you got a good faster solution, would you mind sharing it with the rest of the EE community?
I thought phoffric's question was interesting enough to see what the potential speed gain is, so I went ahead and implemented a version.  I suspect the OP will need a little more time to do this as he's just learning Java.

This is my code (which just uses a random array to create the values for testing the printer).  It's not 100% correct - I think some of the padding needs a little adjustment, but the performance should be basically correct.

As you can see I've kept the original (druk1) and the new (druk2).

On my laptop
 -  druk1 takes between 21ms - 30ms depending on the run.
 - druk2 takes between 4ms - 6ms depending on the run, so about 5x speed up.

I didn't optimize the printing of the titles, which also could certainly be boosted in the same manner.

First time for me writing some Dutch code :)

public class SpeedTest {

	public static void main(String args[]) {
		float[] gespaardBedrag= new float[21];
		float[] jaarKapitaal = new float[21];
		float[] interesten = new float[21];

		Random r = new Random() ;

		for (int i = 0 ; i < gespaardBedrag.length ; i++) {
			gespaardBedrag[i] = (float)(r.nextDouble() * 100000) ;
			jaarKapitaal[i] = (float)(r.nextDouble() * 100000) ;
			interesten[i] = (float)(r.nextDouble() * 100000) ;
		}

		druk1(jaarKapitaal, interesten, gespaardBedrag);
		druk2(jaarKapitaal, interesten, gespaardBedrag);
	}

	private static void padString(StringBuilder output, String inputString, int desiredLength) {
		// Add desiredLength - inputString.length() spaces before adding inputString to output
		// Could be a simple loop, could use lookup tables to make this even faster
		// Doing this yourself is faster than calling String.format() which is another option.
		int add = desiredLength - inputString.length() ;
		for (int i = 0 ; i < add ; i++) { output.append(" ") ; }
		output.append(inputString) ;
	}

	private static void druk1(float[] kapitaal, float[] interesten, float[] gespaardBedrag) {

		long startTime = System.nanoTime();
		// titels uitprinten
		System.out.printf("Per gespaard jaar:%n%-15s %-20s %-15s %-15s %n", "Jaar", "Gespaard Bedrag", "Interesten", "Totaal tegoed");

		for (int i = 0; i < kapitaal.length; i ++) {
			// uitprinten van het gevraagde met de juiste formats

			System.out.printf("na %d jaar\t%-20.2f %-15.2f %-10.2f %n", i+1, gespaardBedrag[i], interesten[i],	kapitaal[i]);
		}
		// printen van de titels van de per 2 gespaarde jaren
		System.out.printf("%n Per gespaarde jaren: %n %-15s %-20s %-15s %-15s %n", "Jaar", "Gespaard Bedrag",
				"Interesten", "Totaal tegoed");

		for (int i = 1; i < kapitaal.length; i +=2) {
			// uitprinten van het gevraagde met de juiste formats
			System.out.printf("na %d jaar\t%-20.2f %-15.2f %-10.2f %n", i + 1, gespaardBedrag[i], interesten[i], kapitaal[i]);
		}

		long difference = System.nanoTime() - startTime;
		System.out.println("\nTotal execution time: " + String.format("%d ms", TimeUnit.NANOSECONDS.toMillis(difference)));
	}

	private static void printValues(int i, float[] kapitaal, float[] interesten, float[] gespaardBedrag, DecimalFormat twoDP) {
		// uitprinten van het gevraagde met de juiste formats
		StringBuilder output = new StringBuilder(500) ;

		//System.out.printf("na %d jaar\t%-20.2f %-15.2f %-10.2f %n", i+1, gespaardBedrag[i], interesten[i],	kapitaal[i]);
		output.append("na " + Integer.toString(i+1) + " jarr\t") ;
		padString(output, twoDP.format(gespaardBedrag[i]), 20) ;
		padString(output, twoDP.format(interesten[i]), 15) ;
		padString(output, twoDP.format(kapitaal[i]), 10) ;

		System.out.println(output.toString()) ;

	}

	private static void druk2(float[] kapitaal, float[] interesten, float[] gespaardBedrag) {
		DecimalFormat twoDP = new DecimalFormat(".##") ;

		long startTime = System.nanoTime();
		// titels uitprinten
		System.out.printf("Per gespaard jaar:%n%-15s %-20s %-15s %-15s %n", "Jaar", "Gespaard Bedrag", "Interesten", "Totaal tegoed");

		for (int i = 0; i < kapitaal.length; i ++) {
			printValues(i, kapitaal, interesten, gespaardBedrag, twoDP);
		}
		// printen van de titels van de per 2 gespaarde jaren
		System.out.printf("%n Per gespaarde jaren: %n %-15s %-20s %-15s %-15s %n", "Jaar", "Gespaard Bedrag",
				"Interesten", "Totaal tegoed");

		for (int i = 1; i < kapitaal.length; i +=2) {
			printValues(i, kapitaal, interesten, gespaardBedrag, twoDP);
		}

		long difference = System.nanoTime() - startTime;
		System.out.println("\nTotal execution time: " + String.format("%d ms", TimeUnit.NANOSECONDS.toMillis(difference)));
	}
}

Open in new window

it really works great, i'm still trying to understand the use of the padstring together with the printvalue method. I havent seen these things yet during the course. but thanks to dpearson i now know that the printf isn't just print something with a given format, but that there's more going on behind the screen. so thank you again, it's something i can keep in mind for the future!
Pretty impressive results:  21ms - 30ms down to 4-6ms
I may have to learn Java and Dutch just to appreciate what you have done. :)
Wonder how the OO suggestion would do?

In general, if using classes and where performance has been determined to be critical, then keep the hottest attributes near the start of the class. There is a balance of course between the hottest idea and the resulting padding that may occur in order to get proper attribute alignment in the class.