Help?

The posts on 4KJO seem to have disappeared. Can the author please contact me? I’m getting a lot of exceptions that are telling me that the jar file is corrupt… but yet it runs just fine.

Also, I thought I’d followed all the “rules” for making the code as small as possible, and my code isn’t really doing THAT much, but I’ve only just now been able to get it under 7 kb. I’m hoping one of the wizards here can take a look and point out any obvious mistakes I’m making.

I’m trying to make an online poker game (server and client in the same jar). Currently it’s Omaha Hi-Lo 8, I will probably change it to Hold 'Em to save a few more bytes.

Thanks in advance.

Edit: No, it doesn’t yet work, there’s a few bugs I still need to fix. I just thought I’d take a look at how I was doing on size, and realized the crisis.

refer to the first post of the Links, tips and goodies thread. It has links to the 4KJO tool I created :slight_smile:

Some suggestions:

I think most of your class size bloat comes from the different API classes you make use of all of which add to the class’s symbol table size.

i would suggest try using only one array and use different Index offsets for logically different instead of many different arrays each representing a different logical component.

Try reducing the number of local variables used. If you can, reuse a local variable for different logical purposes.

try using the ? opertor when conditionally assigning values… e.g for


option = FOLD;
              if (active > 1 && raises < 4) {
                if ((bet+raise) < cash[action]) {
                  if (bet == 0) {
                    option |= BET;
                  } else {
                     option |= RAISE;
                  }
                } else {
                  option |= ALLIN;
                }
              } 

make it:


option = (active > 1 && raises < 4) ?
  option |= ((bet+raise) < cash[action])?
     (bet == 0) ?
       BET
     :
       RAISE
   :
      ALLIN
: 
   FOLD

replace all division where possible by bitwise operation… i.e.

 /2 

to

 >> 1 

if possible convert all for loops to loop backward. The comaprision to 0 test will therefore occur often and be more easily compressable.

[quote=“moogie,post:3,topic:32617”]
Those two take up exactly the same number of bytes…

hmm, in my previous entry it gained me a couple of bytes… perhaps the different bytes used to represent >> 1 was more favorable when compressing my JAR entry?

I was mostly being a smartass. :wink:

/2 and >>1 happen to use the same amount of bytes, and so does /4 and >>2.
But for divisions by 8, 16, and 32, you save one byte by using >> instead.
Divisions by 64 uses the same number of bytes as >> since iconst_N doesn’t go higher than 5, and /64 is >>6.
Using right shift instead of divisions by 128 through 16384 saves one byte.
Over 16384, you’re using the constant pool, so now you’re saving even more by using >>.

So in general, it’s (probably) a good idea to use >>, but for the /2 case, any benefit you saw probably just came from compression randomness. =)

For completeness, it’s worth mentioning proguard automatically replaces all multiplication by powers of 2 with the equivalent shift, as it’s a safe speed & size optimisation.

It doesn’t do the same for division because it’s an unsafe optimisation, due to the 2 operations not being entirely equivalent (/2 rounds toward 0, >>1 rounds toward -ive infinity)
So, adding the shifts manually (where safe to do so) may well save you some bytes.

Funny, I looked right at it at didn’t see it. I also searched for “4KJO” and got no results. Odd.

Anyway, is there any chance you could take a look at the exceptions I’m seeing? I’ll post the jar file I used if you need.

[quote=“moogie,post:3,topic:32617”]
I’ll take a look and see if there’s any way I can trim this down.

[quote=“moogie,post:3,topic:32617”]
I was going to have a single array with different indices being the different variables I needed (for the singleton variables) but it seemed that that would actually add to the size. There’s only a couple of other arrays that I could do this for, but I’ll keep this in mind.

[quote=“moogie,post:3,topic:32617”]
I’ve been trying to reuse wherever possible, but I’ll look harder for more opportunities.

[quote=“moogie,post:3,topic:32617”]
Is this true? I thought someone, way back when, said that this way actually took more bytes…

[quote=“moogie,post:3,topic:32617”]
Will do.

Thanks for taking a look!

[quote=“EnderGT,post:9,topic:32617”]
I’ll take a look and see if there’s any way I can trim this down.
I was going to have a single array with different indices being the different variables I needed (for the singleton variables) but it seemed that that would actually add to the size. There’s only a couple of other arrays that I could do this for, but I’ll keep this in mind.
I’ve been trying to reuse wherever possible, but I’ll look harder for more opportunities.
Is this true? I thought someone, way back when, said that this way actually took more bytes…
Will do.

Thanks for taking a look!
[/quote

I had thought the same about using one monolithic array, but it did end up better as it reduced the symbol table and i was able to use/abuse the monolithic array to perform some game logic by carefully ordering the array and thus reducing the number of conditional statements i needed.

I thought about writing a tool that would parse a java/class file and list potential local variables that could be reused at different points in the execution… perhaps i should do this.

it might be the case that the ? operator takes more bytes, however in the example listed above, it also reduce the number of |= operators… so it may give a reduction.

Your game logic seems very complex with many conditions and states… with out simplifying the logic or abusing some behavior of java or math to represent your game logic I do not think you will be able to fit it with in 4k :frowning:

[quote=“moogie,post:10,topic:32617”]
I’m starting to think the same… I’ve gotten it down to 6037 bytes by inlining the network code instead of using DataInput/OutputStreams, and by removing a few unnecessary states and combining a few others, but I’m not sure what else I’ll be able to remove without making it simply unplayable.

Edit: now 5750 bytes… a few more trouble spots to attack before I switch from Omaha to Hold’Em to save another chunk. I’d rather stay with Omaha if I can - limit hold’em is somewhat boring IMO.