• Welcome to Valhalla Legends Archive.
 

[Java]Access Flags

Started by Tuberload, November 07, 2003, 05:28 PM

Previous topic - Next topic

Eibro

Seems like it'd be more intuitive to work with operator overloads instead of functions like Set/UnSet/etc.
Eibro of Yeti Lovers.

Tuberload

Quote from: Eibro on November 09, 2003, 07:31 PM
Seems like it'd be more intuitive to work with operator overloads instead of functions like Set/UnSet/etc.
I don't understand how it would be more intuitive, but Java does not support operator overloading that I am aware of. I think using Accessor/Mutator methods for setting and getting data works fine, even though I don't even see what Set/Unset methods you are talking about.
Quote"Pray not for lighter burdens, but for stronger backs." -- Teddy Roosevelt
"Your forefathers have given you freedom, so good luck, see you around, hope you make it" -- Unknown

Kp

Quote from: Tuberload on November 09, 2003, 05:49 PM
It does return a null if the flag is not found. So I tried a new method as you suggested. I did away with the allowed() method call, and had the toggleFlags() method check to see if a null is returned and return either the modified access_flags or an unmodified flag value. Here is the new toggleFlags() method:

  public int modify (int access_flags, String flags)
  {
     flags = flags.toLowerCase();
     
     for (int i = 0; i < flags.length(); i++)
     {
        //if (allowed(flags.charAt (i)))
        access_flags = toggleFlags (flags.charAt (i), access_flags);
     }
     return access_flags;
  }
  private int toggleFlags (char flag, int access_flags)
  {
     // If flag is found return modified access_flags
     return allowed_flags.get (String.valueOf (flag)) != null ? access_flags
              ^ ((Integer)allowed_flags.get(String.valueOf (flag))).intValue() : access_flags;
     /*return access_flags ^ ((Integer)allowed_flags.get(String.valueOf (
                                            flag))).intValue();*/
  }

I then tested the two, and found the previous way I was doing it took 100 milliseconds, and this new method took 111. My test code toggles all available flags, plus one that is not available 10,000 times. My test code is as follows:

  AccessFlags test = new AccessFlags();
  int flag = 0x1; // initially set to 'n'
  long time = System.currentTimeMillis();
 
  for (int i = 0; i < 10000; i++)
     flag = test.modify (flag, "nfeuomz");
       
  long time2 = System.currentTimeMillis() - time;
  System.out.println (time2);

As it stands my previous method is faster, although I am sure you, Kp, can point out some areas of interest. I tried to go with your idea of letting the modification take place without an initial check, and then just handling any unwanted returns.
Well, some of the performance hit might be coming from multiply querying the hash table.  Try using this for your toggle method:

  private int toggleFlags (char flag, int access_flags)
  {
   Object o = allowed_flags.get (String.valueOf (flag));
   if (o != null)
       access_flags ^= ((Integer) o).intValue ();
   return access_flags;
  }

This way, you perform only one lookup, and one class casting checking.  If the lookup fails (null return), you skip the conditional and return without doing any additional work.  Note that the cast to Integer cannot be performed until after it's confirmed that the returned Object was not null.  Otherwise, I'd have cast the return immediately and stored it in an Integer reference for readability's sake.

Quote from: Tuberload on November 09, 2003, 05:59 PM
I also tried placing the toggleFlags() method in a try/catch statement to handle the NullPointerException that would be thrown on the event of a bogus flag.

  try
  {
     access_flags ^= ((Integer)allowed_flags.get(String.valueOf (
                                            flag))).intValue();
  }
  catch (NullPointerException exc) {}
  return access_flags;

The time results were 430 milliseconds. Maybe using Java's try/catch statements is not be a good idea for the sake of performance.
Yes; I knew that in C++, use of exceptions tended to be much slower than developer-implemented error checking.  I'd hoped that it wouldn't be as bad in Java, since they had a chance to implement exceptions directly into the VM.  Apparently not. :P
[19:20:23] (BotNet) <[vL]Kp> Any idiot can make a bot with CSB, and many do!

Banana fanna fo fanna

After writing BeefBot, a high-performace, plugin-oriented (and horribly unreliable due to a shitty reactor implementation) Java bot, I did some research into the best way to implement a user database.

Basically, you're going to want to have a hashmap of hashmaps. The top hashmap is one keying lowercase usernames to their hashmap of properties. Perhaps this is overkill for your application; you may want to use a bitfield/custom class. I chose a hashmap because I stored lots of information. After changing a user, mark them as dirty. Every few minutes have a daemon write it to disk.

The "best" way to do this is a BTree...but I don't have time to create a good implementation :)

You may investigate SQLLite...but I know you really want to write it yourself, don't you?

Tuberload

Quote from: St0rm.iD on November 11, 2003, 02:24 PM
After writing BeefBot, a high-performance, plugin-oriented (and horribly unreliable due to a shitty reactor implementation) Java bot, I did some research into the best way to implement a user database.

Basically, you're going to want to have a hashmap of hashmaps. The top hashmap is one keying lowercase usernames to their hashmap of properties. Perhaps this is overkill for your application; you may want to use a bitfield/custom class. I chose a hashmap because I stored lots of information. After changing a user, mark them as dirty. Every few minutes have a daemon write it to disk.

The "best" way to do this is a BTree...but I don't have time to create a good implementation :)

You may investigate SQLLite...but I know you really want to write it yourself, don't you?

Yes, I know that I am re-inventing the wheel, but I do like to do it myself. :) It helps me to learn the language better when I do it myself and I don't have time constraints. This was however a small part of the bot I am creating and I had hoped it would help others, while helping myself. I do however use Hashtables extensively in my bot to store user information though. I create a BotMember class that stores all the information, then store it in a Hashtable. I serialize the BotMember classes when a member leaves the channel and deserialize them once on join/user events to save on memory at the sake of performance. If the local database does not contain a previously saved member I just create a new one.

Kp: I use the ternary (Sp?) operator to do the exact thing you do don't I? It checks to see if the value is null and returns the original flags if it is, otherwise it returns the modified flags. If I am missing something please let me know, but I don't see the difference between my code and yours except how it was done. Never mind I see what you are saying, stupid me. In my drive to make the method as small as possible I did create added overhead. Thank you once again for your help.
Quote"Pray not for lighter burdens, but for stronger backs." -- Teddy Roosevelt
"Your forefathers have given you freedom, so good luck, see you around, hope you make it" -- Unknown

Kp

#20
Quote from: Tuberload on November 27, 2003, 04:30 AM
If the local database does not contain a previously saved member I just create a new one.

I understand the value of this, and once did it myself.  However, I discontinued the practice a couple years ago, for the following reason: one-shot visitors.  If you hang out in a popular channel (e.g. Op [vL], or any other place where people just stop by for a bit), you'll get a lot of entries created from one-shot visitors who never return, or at least weren't interesting enough to merit remembering.  Additionally, massbots and certain types of floodbots can be very damaging if you create an entry for every name you see them use...  It's much better to only create a user entry when an authorized user directs that it be done.  That will (mostly) cut down on bogus / garbage db entries.

Quote from: Tuberload on November 27, 2003, 04:30 AM
Kp: I use the ternary (Sp?) operator to do the exact thing you do don't I? It checks to see if the value is null and returns the original flags if it is, otherwise it returns the modified flags. If I am missing something please let me know, but I don't see the difference between my code and yours except how it was done. Never mind I see what you are saying, stupid me. In my drive to make the method as small as possible I did create added overhead. Thank you once again for your help.

:)  It's unfortunate that the compiler isn't quite smart enough to be able to optimize your code to look like mine automatically.  I suspect it could, if Java had a method to declare methods as being 'const' with respect to their objects. *cough*  C++ can do this, Java can't -- the only way Java can create const objects is by having the object artificially enforce that, such as by not having any public mutator methods.

[Edit: minor wording change.]
[19:20:23] (BotNet) <[vL]Kp> Any idiot can make a bot with CSB, and many do!