News:

Simutrans Wiki Manual
The official on-line manual for Simutrans. Read and contribute.

Passengers and goods using stations outside city limits are not counted

Started by Rollmaterial, August 13, 2017, 03:12:22 PM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Rollmaterial

Passengers and goods that use stations located outside city limits are not counted in the city's stats as "transported", "sent" or "goods supplied".

jamespetts

Thank you for the report. This is a complex issue to deal with. This is because passengers and goods register successfully completing their journeys after they actually reach their destination. By that time, there is no longer any record kept of whether the actual building from which they started is or is not within city limits. All that is stored for each unit of mail/passengers/goods is the origin stop.

Changing this would require every unit of passengers/mail/goods to record its starting point, an additional 24 bits per packet, which might significantly increase memory bandwith usage (although I have not tested this).

To know whether this is worthwhile, it would be helpful to have some data on the extent to which this issue is marginal or significant in real gameplay. Are you able to help with that at all?
Download Simutrans-Extended.

Want to help with development? See here for things to do for coding, and here for information on how to make graphics/objects.

Follow Simutrans-Extended on Facebook.

Rollmaterial

I have here two nearby cities of similar size. Hodwell has its station within the city limits, Tumpish St. Margaret has it outside. Hodwell has somewhat more growth.

.sve: https://drive.google.com/file/d/0ByLSSg3gXTz-YjlLQmE0ZjZvRms/view?usp=sharing

DrSuperGood

I would say give the origin location per packet approach a try as it is by far the simplest and most accurate. If one is careful with struct packing it might raise memory per packet less than 3 bytes, on the other hand it could also raise memory per packet by 4 bytes or more in order to retain efficient alignment.

Another approach would be to assign stops an origin distribution factor based on the statistics of which city people are coming from. If City A has 2 times more people originating from it that use the stop than City B then 2/3 of the arrival credit is sent to City A and 1/3 to City B. This is not perfectly accurate and excessively hacky/complex to program but should be accurate enough for most purposes and does not require increasing goods packet size.

jamespetts

Rollmaterial: it is hard to draw much from the screenshot/saved game, as it is difficult to control usefully for other factors (and there are a huge range of other factors that might in principle be relevant given your description).

Dr. Supergood - may I ask how one might go about being careful as to struct packing?

Generally - I should note that given the enormous amount of time that each change takes, the very long list of changes needed to achieve balancability, the critical importance of balancability and the fact that this is not gamebreaking, it is likely to be some time before I am able to dedicate a significant amount of time to this.
Download Simutrans-Extended.

Want to help with development? See here for things to do for coding, and here for information on how to make graphics/objects.

Follow Simutrans-Extended on Facebook.

DrSuperGood

QuoteDr. Supergood - may I ask how one might go about being careful as to struct packing?
Usually by reading the compiler manual as to how it packs structs. Since most compilers aim for efficient code, memory works in a similar way independent of instruction set and other factors there are some general rules. Structs and classes are packed in the same way.

Since aligned reads, reads where the address number is a multiple of the length of element being read, are faster than unaligned reads struct size is usually a multiple of the biggest primitive element. For example if a struct contains a 64bit (8byte) primitive it will round struct size up to the next 8 bytes, padding with unused bytes as appropriate. What this means is that a struct consisting of a 64bit primitive and 8bit primitive will use 16 bytes. This behaviour can be overwritten with compiler specific macros or flags and alignment is not so important on modern processors which have considerably better unaligned reads however it still is recommended for optimum performance, hence why it is the default behaviour.

For some reason (I do not know why...) compilers insist on keeping the physical order of fields the same as the declared order. Since reads should be aligned it means that mixing fields of different primitive type length result in wasted space. For example declaring a struct with an 8bit primitive, a 64bit primitive and then another 8bit primitive will result in a struct with size of 24 bytes of which 14 bytes are padding. The same struct could be declared as 2 8bit primitives and a 64bit primitive and it will only be 16 bytes of which 6 bytes are padding (saving of 8 bytes).

Nested structs are another problem. They are aligned to the largest primitive size and enforce a minimum alignment requirement of their alignment requirement on the parent struct.

Any struct or class that has virtual methods requires a virtual lookup table pointer which is usually a hidden pointer field at the start of the struct. This will be 4 bytes for 32bit builds and 8 bytes for 64bit builds. Alignment requirements still apply so that a struct with virtual methods and a 64bit primitive will use 16 bytes of which 4 bytes are padding.