quality of food and booze

Winterbay

Active member
Test 1
1000 Iterations full loop (type="food" took 8073ms
Test 2
1000 Iterations (full loop, fullness > 0) took 12169ms
Test 3
1000 Iterations (fullness.text) took 4118ms
Test 4
1000 Iterations (fullness.text(pre loaded)) took 966ms
Test 1
1000 Iterations full loop (type="food" took 8137ms
Test 2
1000 Iterations (full loop, fullness > 0) took 12462ms
Test 3
1000 Iterations (fullness.text) took 4094ms
Test 4
1000 Iterations (fullness.text(pre loaded)) took 971ms
Test 1
1000 Iterations full loop (type="food" took 8198ms
Test 2
1000 Iterations (full loop, fullness > 0) took 12297ms
Test 3
1000 Iterations (fullness.text) took 3975ms
Test 4
1000 Iterations (fullness.text(pre loaded)) took 965ms

I feel that my computer is a lot older than yours... :)

Code:
> call speed.ash

Test 1
1000 Iterations full loop (type="food" took 91235ms
Test 2
1000 Iterations (full loop, fullness > 0) took 125781ms
Test 3
1000 Iterations (fullness.text) took 22016ms
Test 4
1000 Iterations (fullness.text(pre loaded)) took 10625ms
Test 1
1000 Iterations full loop (type="food" took 91078ms
Test 2
1000 Iterations (full loop, fullness > 0) took 125782ms
Test 3
1000 Iterations (fullness.text) took 22015ms
Test 4
1000 Iterations (fullness.text(pre loaded)) took 10609ms
Test 1
1000 Iterations full loop (type="food" took 91235ms
Test 2
1000 Iterations (full loop, fullness > 0) took 126000ms
Test 3
1000 Iterations (fullness.text) took 22015ms
Test 4
1000 Iterations (fullness.text(pre loaded)) took 10625ms

The overall conclusions still stand though, even though the impact of different options is very different.
 

Veracity

Developer
Staff member
Well...

Iterating through every item ID to find foods is slower than iterating just through the foods
Building a map of foods once and using it 1000 times is faster than building it 1000 times
ASH caches data files you read, so you can do multiple file_to_map calls and read the disk only once - although it will parse the contents and generate the map however many times.
The "fullness" function is slow - for some reason.

Something you didn't try was combining observation 1 & 2: building a map of only foods once and iterating through it 1,000 times. For example:

Code:
	print("Test 5");

	boolean[item] onlyfood;
	foreach it in $items[] {
		if ( item_type(it) == "food" ) {
			onlyfood[ it ] = true;
		}
	}
	
	starttime = gametime_to_int();
	for i from 1 to 1000 {
		int epiccount = 0;

		foreach it in onlyfood {
			if (it.fullness > 0 & it.quality=="epic" ) {
				epiccount +=1;
			}
		}
	}
	print("1000 Iterations (generated food map) took " + (gametime_to_int() - starttime) + "ms");
yields (1 iteration):

Code:
Test 1
1000 Iterations full loop (type="food" took 16124ms
Test 2
1000 Iterations (full loop, fullness > 0) took 24883ms
Test 3
1000 Iterations (fullness.text) took 7452ms
Test 4
1000 Iterations (fullness.text(pre loaded)) took 2084ms
Test 5
1000 Iterations (generated food map) took 2035ms

And another couple observations:

"if ( a & b )" does work: it evaluated a and b, does an arithmetic "and" on the 2 values, and coerces the result into a boolean.
What you REALLY want is "if ( a && b )" which will evaluate a, and only if that is true, evaluate b.

Observation 4 is that fullness is a slow function. If you only want to look at foods with fullness > 0, only put such foods in your map. Thus:

Code:
	print("Test 6");

	boolean[item] onlyfillingfood;
	foreach it in $items[] {
		if ( item_type(it) == "food" && it.fullness > 0 ) {
			onlyfillingfood[ it ] = true;
		}
	}
	
	starttime = gametime_to_int();
	for i from 1 to 1000 {
		int epiccount = 0;

		foreach it in onlyfillingfood {
			if (it.quality=="epic" ) {
				epiccount +=1;
			}
		}
	}
	print("1000 Iterations (generated filling food map) took " + (gametime_to_int() - starttime) + "ms");

yields (fixing & to && everywhere, as well):
Code:
Test 1
1000 Iterations (full loop type="food") took 4523ms
Test 2
1000 Iterations (full loop, fullness > 0) took 15956ms
Test 3
1000 Iterations (fullness.text) took 7352ms
Test 4
1000 Iterations (fullness.text(pre loaded)) took 1829ms
Test 5
1000 Iterations (generated food map) took 1726ms
Test 6
1000 Iterations (generated filling food map) took 870ms
 
Last edited:

Veracity

Developer
Staff member
I was curious about something else: when looking at why fullness was slow, I observed that we had to look up foods by name. It struck me that an item number lookup might be better. At which point, I realized that not all foods are items: Cafe offerings and sushi, for example. So, reading fullness.txt into an array of items will strip out the non-items.

I included the map size and also reset & printed the epiccounter in the above tests and reran them:

Code:
Test 1
1000 Iterations (full loop type="food") took 4408 ms and found 24 epic foods
Test 2
1000 Iterations (full loop, fullness > 0) took 13496 ms and found 24 epic foods
Test 3
1000 Iterations (fullness.text) took 7338 ms and found 24 epic foods
Test 4
1000 Iterations (fullness.text(pre loaded) map size = 412) took 1817 ms and found 24 epic foods
Test 5
1000 Iterations (generated food map size = 415) took 1836 ms and found 24 epic foods
Test 6
1000 Iterations (generated filling food map size = 409) took 877 ms and found 24 epic foods
I wondered about the 6 "fullness == 0" foods in the item list.

> ashq foreach it in $items[] if ( item_type( it ) == "food" && it.fullness == 0 ) print( it )

Children's Meal of the Damned
spooky frank
plate of franks and beans
flask of peppermint oil
quantum taco
s'more

For what it's worth, here is the modified test program:

Code:
int starttime = 0;
int epiccount = 0;

boolean[item] food;

for a from 1 to 3 {


	print("Test 1");
	starttime = gametime_to_int();
	epiccount = 0;
	for i from 1 to 1000 {
		foreach it in $items[] {
			if((item_type(it) == "food") && (it.quality=="epic") ) {
				epiccount +=1;
			}
		}
	}
	print("1000 Iterations (full loop type=\"food\") took " + (gametime_to_int() - starttime) + " ms and found " + ( epiccount / 1000 ) + " epic foods");


	print("Test 2");
	starttime = gametime_to_int();
	epiccount = 0;
	for i from 1 to 1000 {
		foreach it in $items[] {
			if((it.fullness > 0) && (it.quality=="epic") ) {
				epiccount +=1;
			}
		}
	}
	print("1000 Iterations (full loop, fullness > 0) took " + (gametime_to_int() - starttime) + " ms and found " + ( epiccount / 1000 ) + " epic foods");



	print("Test 3");
	starttime = gametime_to_int();
	epiccount = 0;
	for i from 1 to 1000 {
		int[item] food;
		file_to_map("fullness.txt", food);
		foreach it in food {
			if((it.fullness > 0) && (it.quality=="epic") ) {
				epiccount +=1;
			}
		}
	}
	print("1000 Iterations (fullness.text) took " + (gametime_to_int() - starttime) + " ms and found " + ( epiccount / 1000 ) + " epic foods");

	
	print("Test 4");
	int[item] food;
	file_to_map("fullness.txt", food);
	starttime = gametime_to_int();
	epiccount = 0;
	for i from 1 to 1000 {

		foreach it in food {
			if((it.fullness > 0) && (it.quality=="epic") ) {
				epiccount +=1;
			}
		}
	}
	print("1000 Iterations (fullness.text(pre loaded) map size = " + count(food) + ") took " + (gametime_to_int() - starttime) + " ms and found " + ( epiccount / 1000 ) + " epic foods");
	

	print("Test 5");

	boolean[item] onlyfood;
	foreach it in $items[] {
		if ( item_type(it) == "food" ) {
			onlyfood[ it ] = true;
		}
	}

	starttime = gametime_to_int();
	epiccount = 0;
	for i from 1 to 1000 {

		foreach it in onlyfood {
			if (it.fullness > 0 && it.quality=="epic" ) {
				epiccount +=1;
			}
		}
	}
	print("1000 Iterations (generated food map size = " + count( onlyfood) + ") took " + (gametime_to_int() - starttime) + " ms and found " + ( epiccount / 1000 ) + " epic foods");

	Print("Test 6");

	boolean[item] onlyfillingfood;
	foreach it in $items[] {
		if ( item_type(it) == "food" && it.fullness > 0 ) {
			onlyfillingfood[ it ] = true;
		}
	}

	starttime = gametime_to_int();
	epiccount = 0;
	for i from 1 to 1000 {

		foreach it in onlyfillingfood {
			if (it.quality=="epic" ) {
				epiccount +=1;
			}
		}
	}
	print("1000 Iterations (generated filling food map size = " + count( onlyfillingfood) + ") took " + (gametime_to_int() - starttime) + " ms and found " + ( epiccount / 1000 ) + " epic foods");
}
 

matt.chugg

Moderator
I thought that the behaviour of & was to only evalute the second comparison if the first is true! I forgot it was &&!

I love the way you think veracity, I wouldn't have thought of using my own generated map instead of fullnesss.

WHen I get to work, i'll run the script on the same computer as I ran the first one and see how much time you saved on the same box! :)
 

Winterbay

Active member
Interesting. I just ran the test script on my work laptop adn despite it being slower (in the MHz sense) and havign less RAM it apparently runs Java faster since the time above were cut with a factor of 2-9 (depending on test). I wonder why that is.
 

matt.chugg

Moderator
original results:
Test 1
1000 Iterations full loop (type="food" took 8073ms
Test 2
1000 Iterations (full loop, fullness > 0) took 12169ms
Test 3
1000 Iterations (fullness.text) took 4118ms
Test 4
1000 Iterations (fullness.text(pre loaded)) took 966ms

veracity's refatorcted version:

Test 1
1000 Iterations (full loop type="food") took 1961 ms and found 24 epic foods
Test 2
1000 Iterations (full loop, fullness > 0) took 5683 ms and found 24 epic foods
Test 3
1000 Iterations (fullness.text) took 3659 ms and found 24 epic foods
Test 4
1000 Iterations (fullness.text(pre loaded) map size = 412) took 758 ms and found 24 epic foods
Test 5
1000 Iterations (generated food map size = 415) took 761 ms and found 24 epic foods
Test 6
1000 Iterations (generated filling food map size = 409) took 351 ms and found 24 epic foods

Very significant increases in speed,
Test 6 : 351ms for 1000 iterations if pretty impressive! /me loves .ash

for info: thats on xeon W3530 2.8gh (I did set affinity to cpu 0 on javaw.exe, although I don't know if java even uses multiple cores, which incresed tests 1 to 4 by about 200ms?) x64 windows 7 3gb ram
 
Last edited:

fianor

Member
And keeps epic spleeners as well!

it.quality doesn't seem to give any results for spleeners, unless I got something wrong

Code:
foreach it in $items[] {
	if ((it.quality=="epic") & (item_amount(it) > 0)) print("You have " + item_amount(it) + " of " + it + " which is " + it.quality + " quality","red");
	if ((it.quality=="awesome") & (item_amount(it) > 0)) print("You have " + item_amount(it) + " of " + it + " which is " + it.quality + " quality","blue");
	if ((it.quality=="good") & (item_amount(it) > 0)) print("You have " + item_amount(it) + " of " + it + " which is " + it.quality + " quality","green");
	if ((it.quality=="decent") & (item_amount(it) > 0)) print("You have " + item_amount(it) + " of " + it + " which is " + it.quality + " quality");
	if ((it.quality=="crappy") & (item_amount(it) > 0)) print("You have " + item_amount(it) + " of " + it + " which is " + it.quality + " quality","gray");
}

returns only food and booze results, regardless of any spleeners I'm holding. Removing & (item_amount(it) > 0) also only provides food and booze.
 

Veracity

Developer
Staff member
That is correct. KoL does not provide us a "quality" for spleen items. Theraze was incorrect and/or optimistic with the "epic spleener" comment, since there is no such thing.
 

Theraze

Active member
Yep... Veracity explained that in another post. Only food/drink officially has quality. If spleen ever does get quality, that will work, until then, you'd need to calculate it yourself...
 

fianor

Member
yeah, lots of calculating myself being done already. I only mentioned it in case someone came along and just trusted the code worked without testing and did something silly with all their astronaut ice cream by accident. Granted that person probably wouldn't have read the rest of the thread either so ...


anyway, here's hoping tptb give us spleener.quality someday also :)
 

Theraze

Active member
Alternatively, if you want to only take epic consumables, those in the >5 adventures average, could do:
Code:
  foreach it in $items[]
  {
    float gainadv;
    int totalcost;
    switch (type)
    {
      case "food":
        totalcost = it.fullness;
        gainadv = totalcost > 0 ? (averange(set_range(it.adventures)) / totalcost) : 0;
        break;
      case "drink":
        totalcost = it.inebriety;
        gainadv = totalcost > 0 ? (averange(set_range(it.adventures)) / totalcost) : 0;
        break;
      case "spleen":
        totalcost = it.spleen;
        gainadv = totalcost > 0 ? (averange(set_range(it.adventures)) / totalcost) : 0;
        break;
      default:
        continue;
        break;
    }
    if (gainadv > 5) { do something with good consumables }
    else { get rid of bad stuff }
  }
 
Top