C++

Speak about everything in regards to Crossfire.

Moderator: Board moderators

mwedel
Regular
Posts: 86
Joined: Tue Jul 17, 2007 5:23 am
Location: Santa Clara, CA, USA

Post by mwedel »

In terms of map load times, analysis would need to be done to see the real cause. Some of it may be time it takes to parse strings, but I suspect a fair amount may also be the fact that a lot of things are stored in link lists, and updates of those could be a be a factor.

I also vote against a binary format - it would seem to add a lot of complication (you now need some mapping of that binary format to other values within the game (name, archetype, etc). And those lookups may not necessarily go away on a binary format - just the lookup method changes.

Limiting number of items is simplest - right now, containers are unlimited - one could limit that to some number. Likewise, number of objects on a space is unlimited - a suggestion on that has been once the pile of items reach some amount, they spill over to adjacent spaces. If those adjacent spaces are also full, could disallow the drop in the first place (no space to put it )

In terms of SDL, including it just for timer support would seem overkill, since timer support is actually pretty simple.

For graphics, that is all done in the client - I can't imagine what type of graphics would be included in the server, other than a recombining of the server and client, which would seem to be going in the wrong direction.
Panthera Leo
Luser
Posts: 19
Joined: Sun Aug 10, 2008 12:17 am

Post by Panthera Leo »

Another idea to speed the load up maybe to count the items in a map, leaving behind pointers to the first entry of each item. Then go back and load them once the list has been initialized to the proper size. It would save having to reset the 'next' and 'prev' pointers every time.

Ok, no binary format, understood. As for the mapping of the values?

Consider what's actually being done. Value in memory of the keyword "arch" plus it's separating white space is "01100001 01110010 01100011 01101000 00001010". Before the value of that string is passed back, a white space charter that delicates the words must be read in, and replaced with a null terminator. So that string becomes "01100001 01110010 01100011 01101000 00000000". For anything to be done with that all five bytes must be perfectly matched, one byte at a time from a internal 'for' loop in 'strcmp'.

Numbers are a bit more difficult as they must not only be read in, they must be converted into a value a integer can use.


The only technical difference between that and binary is only one byte needs to be read in, the first byte. No white spice is considered, no null terminator added. The value is fed directly into a integer type or 'char'. No for loop is called! It's just a simple number comparison to find out what to do next. Does the value of 'a' match the value the value read in?

If it does, a string or number may effectively be bit-copied right into the relevant variable. Finished and done before strcmp even has time start it's for loop!

Now, how that would be done in 'C' I'm no longer familiar enough to know off the top of my head. How I'd do that in C++ is to just flip a switch in the object that read in the data to tell it to just read and write the raw binary instead of converting to and from plain text.

Just in case you cared for future reference.

Edit: The only foreseeable problem would be a difference in word sizes (32 vs 64) or non-standard variable implementations. Though steps could be taken for that.

Still, no, is understood. I'm just not sure where your're coming from.
mwedel
Regular
Posts: 86
Joined: Tue Jul 17, 2007 5:23 am
Location: Santa Clara, CA, USA

Post by mwedel »

Just for sake of discussion:

If you have a binary format, you may have something like a type value followed by a value. So lets say you are use 32 bit type values, and you define 1 as the arch name.

Now at that point, you now either need to read in the string value of the arch name - having it binary saves you a little time as you don't need to parse the string as much, but you still need to say that 'I got the name sword, now I need to use that name to look up the sword archetype, make a copy, etc'.

The other possibility is that you assign a binary value for such strings, so maybe 234 is the binary value for sword. However, you still need to find the sword archetype, do the copying, etc. And know that 234 is the sword item requires a lot more synchronization all around.

Note that crossfire currently uses lex for parsing strings, which is actually very efficient - the code it generates is not really readable, but is basically a binary lookup table of various sorts.

But my point about efficiency is this: If you just had the lex loader go through and parse a very large map file, I suspect it would do it in very little time.

For each object loaded, it has to do several things:
- find the archetype for the object, and make a new object from that
- put other values from the loaded object (custom attributes) into that object structure. For each string, this means finding the shared string reference (and if shared strings were not used, allocating space and copying data into that space)
- insert that into the map, updating linked lists.

The time it takes to clear out the next/prev pointers is minimal - probably close to a single cpu cycle. By doing all operations on the object at the same time, at least you are keeping some cache coherency which probably improves performance.

But the slowest point in that process is most likely inserting into the map, as that can be an O(n^2) operations, where n is the number of objects on a space. This is because for each insertion, it will have to traverse the list of objects already on that space/in that object to figure out where to insert - I think when loading maps, we at least don't bother checking merge logic, but not 100% sure on that.
Panthera Leo
Luser
Posts: 19
Joined: Sun Aug 10, 2008 12:17 am

Post by Panthera Leo »

If that is the case then, and I understand correctly, then a iterator will fix that.

At any rate, I grew tired of waiting for a proper place to submit my work. ;)

http://sourceforge.net/projects/crosfirepp/

If you have the interest or questions each night I work on the code I'll update the SVN. Hopefully my work is about to take off as I'm wrapping up with the basic data structures. I've had too many delays, and it's taken me way longer to unravel and confirm all the ways their used. Hazard of having code that's changed hands over such a long period of time maybe?

Hopefully though, that will be a thing of the past when I'm done as everything should be in self contained, modular units.

Key changes so far:
  • Everything is accessed though a get and set function. Edit: I've taken care of comparability with this methodology with the 'wrapper' template.
  • Everything is carefully packed into it's it's own logical divisions. Everything map related is in the map class, and everything object related is in or derived from the object class.
  • I've used as much of the standards as I'm able.
If you feel the need to add to the code or critique it, do not under any circumstance violate those three things! (I know about the C99 integer types, I'll step them down to C89 if I must once I get a working version.) They've a pain for even me to follow, but they are a important feature. They're there with the goal that the code be easy to follow, change, or out-right replace sections of it 10 or even 20 years from now without having to reverse engineer the entire code. (Like say I am now :P )
Post Reply