Jump to content

Devnote Tuesday: Smashing Buttons


SQUAD

Recommended Posts

11 hours ago, linuxgurugamer said:

Persistent Dynamic Pod Names, hope to release in a few days.  Will be able to assign names to individual command pods, as well as having names generated using a predefined template

Thank squad for 64bit. =)

So I have my RSS Apollo style capsule called Hermes, and your mod could automatically name all launched ones Hermes 1 to Hermes n?

Link to comment
Share on other sites

Why can't ya'll have a constant alpha version for testing on steam? Not trying to be someone who begs or wastes time, But isn't that a quick thing to do?

As in alpha etc,,, Like making the ability to test 1.2 just say a warning to only do it if you:

A. Know what you are doing,

B. Backup the game before,

C. All of the above.

Does that lay it out nicely?

Edited by Mr. Quark
Link to comment
Share on other sites

19 minutes ago, Mr. Quark said:

Why can't ya'll have a constant alpha version for testing on steam?

There are some very good "Developer Articles" by @Ted describing how Squad's dev process works and a number of the recent devnotes have also talked about changes.

It appears to be mostly due to two main reasons.  First, no matter how many warnings and disclaimers are added you will always get people who either don't like something that's in development or can't accept that daily/weekly builds will sometimes have bugs that prevent it running at all or, even, who lose their save, kicking up a fuss.  It really isn't worth the extra hassle and/or pressure on the stability of the community.  Secondly, there isn't a version with all the work currently under development.  Changes only get merged into the "main" branch once they work well enough by themselves which, certainly in the case of larger changes, means putting them through an internal QA cycle as a separate build.  Even if they pass QA that doesn't mean they will immediately get merged into the main branch.

Link to comment
Share on other sites

3 hours ago, Navy2k said:

Thank squad for 64bit. =)

So I have my RSS Apollo style capsule called Hermes, and your mod could automatically name all launched ones Hermes 1 to Hermes n?

Exactly, and that is the simplest case.

For example, let's say that you launch it on a standard rocket, but the number of stages varies depending on the cargo/destination.  You could define a template something like this:

Hermes-<numstages> #hcnt#

Then, looking at a series of launches

First launch would be a single stage:  Hermes-1 1
Second launch would be three stages: Hermes-3 2
Third launch would be two stages:  Hermes-2 3

Etc.  You will be able to do a lot with the templates.

 

 

Link to comment
Share on other sites

 

Quote

The only way in which they can be safer is that they don't allow you to mess with the index in the loop body which is usually more of a hindrance than a help.

Well, except that index errors are easily the no.1 source of bugs in any language that doesn't support enumerators natively...

20 hours ago, Padishar said:

Can you provide an example of a foreach loop being faster than a (correctly written) for loop?  Given what the compiler and runtime does, I can't see any way that this could ever be the case.

First of all, List<T> is heavily optimized for index searches, so accessing an index is cheap. Like all optimizations, this comes with a price. List<T> allocates quite a lot of memory, especially for big collections. Indexed search has a cost of O(1) for List<t>, so iterating over a full list has O(n). But List<T> doesn't handle well insertion or removal operations.

There are collection types that can be iterated, but are not naturally indexed. For example, an ordered List is usually not indexed, but it is very fast when inserting elements. If you try to iterate such a list (e.g. via the Extension method ElementAt(int)), you end up with O(n²).

Second, the enumerator may have knowledge of the data source that you don't have in client code, and optimize accesses. For example, if you have a remote data source like a data base, fetching single items one after another may be very expensive. But an enumerator can optimize depending on the data source. E.g. , table.where(x => x.Name == "Monger") may decide instead of fetching all data base items, iterating over them and returning a filtered view, to ask the database directly for a filtered result by creating a proper SQL query. LinqToSQL makes heavy use of that.

If you work against interfaces (like you should), you are usually not aware of the collection implementation. In some cases, accessing via index is slightly more efficient than via enumerator. In some cases, accessing via index is really, really bad.

 

tl;dr: Don't assume that all collections work like List<T>.

Link to comment
Share on other sites

1 hour ago, linuxgurugamer said:

Exactly, and that is the simplest case.

For example, let's say that you launch it on a standard rocket, but the number of stages varies depending on the cargo/destination.  You could define a template something like this:

Hermes-<numstages> #hcnt#

Then, looking at a series of launches

First launch would be a single stage:  Hermes-1 1
Second launch would be three stages: Hermes-3 2
Third launch would be two stages:  Hermes-2 3

Etc.  You will be able to do a lot with the templates.

 

 

So in my case more like Hermes-17 1 :wink:

Thanks for the clarification, definitely on my watchlist then, so I can charge the according crews for removing their debris.

Link to comment
Share on other sites

1 hour ago, Monger said:

Well, except that index errors are easily the no.1 source of bugs in any language that doesn't support enumerators natively...

That's a rather sweeping generalisation that certainly isn't true for me when writing in any language, whether it has native enumerators or not...

1 hour ago, Monger said:

First of all, List<T> is heavily... [snip]

tl;dr: Don't assume that all collections work like List<T>.

I don't need a lesson on collection data types, thanks.  We're not talking in the context of best practices for general collection datatypes, we're talking in the context of writing code for Unity (where the Unity compiler is used) and, more specifically, in the context of minimising the garbage created by code in KSP, where virtually every collection you ever see is either a List<T> or a class that indirects to a contained List<T>.  Obviously, if the object has an index operator that has to count through the collection then the enumerator could well be faster but it will always result in garbage so that type of collection really wouldn't be a good idea for any sort of hot code in KSP.

The main point of this discussion is that, if you compile your code using the Unity compiler, every use of foreach, regardless of whether the enumerator is a struct or a class, will allocate memory from the heap.  To fix these issues in KSP, Squad have to either replace the uses of foreach or switch to a compiler that doesn't box struct enumerators to dispose of them.  I presume they didn't want to change compiler because it would probably mean some serious disruption to their build processes etc. and, besides, when talking about iterating through List<T>, a simple for loop is not a lot harder to read or maintain than a foreach and, as one of the Squad devs mentioned, also allows much greater flexibility over how the enumeration proceeds.

I'm certainly not recommending that all modders replace foreach with for.  If they don't use the Unity compiler then they shouldn't suffer from the garbage issue and the performance difference, with anything remotely complex in the loop, will be negligible.  The thing most modders need to look out for is using the LINQ-like chaining extensions (or actual LINQ queries), some of which result in the allocation of large amounts of garbage, especially when lambdas are used carelessly, resulting in the creation of closures.

Link to comment
Share on other sites

On 6/30/2016 at 7:46 AM, Padishar said:

I'm certainly not recommending that all modders replace foreach with for.  If they don't use the Unity compiler then they shouldn't suffer from the garbage issue and the performance difference, with anything remotely complex in the loop, will be negligible. 

For mod authors, I take it this means that foreach is fine when compiled with Visual Studio or Xamarin Studio. And that these would be generally recommended over the old Unity monodevelop?

Edited by bos
Link to comment
Share on other sites

3 minutes ago, bos said:

For mod authors, I take it this means that foreach is fine when compiled with Visual Studio or Xamarin Studio instead of the Unity monodevelop?

Using foreach is slightly slower than using a plain for loop though it only really makes much of a difference if you are looping a huge number of times and/or the loop body is very small.  The most important thing is that foreach will not incorrectly allocate struct enumerators on the heap causing garbage.  If you look at the List<T>.GetEnumerator function you see it returns a List<T>.Enumerator struct, this is fine.

However, some KSP classes that wrap a List<T> (e.g. PartModuleList) return an IEnumerator from their GetEnumerator function and, because that is an interface, the object returned gets allocated on the heap, causing garbage, even though the enumerator object is actually the same List<T>.Enumerator struct underneath.  Some other classes, most notably VesselCrewManifest, do some complex stuff in GetEnumerator that creates lots of garbage, even though it does return a struct that gets allocated on the stack.  I do expect that these sort of issues will be addressed during the code cleanup so there is probably no need to worry about them unduly.

Link to comment
Share on other sites

On 6/29/2016 at 10:39 AM, xEvilReeperx said:

The bug's in the compiler used, not the runtime itself.

On 6/29/2016 at 0:57 PM, Padishar said:

Note @xEvilReeperx's comment above (and my confirmation) that foreach only gives  garbage problems when the code is compiled with the compiler that is shipped as part of Unity.  If you use VisualStudio (or, probably, a recent version of MonoDevelop) then you don't really need to change foreach at all.

Thank you both (Yes, I needed to see this twice to understand it). You may have saved all the hair on my head.

Link to comment
Share on other sites

14 hours ago, Padishar said:

The most important thing is that foreach will not incorrectly allocate struct enumerators on the heap causing garbage.  If you look at the List<T>.GetEnumerator function you see it returns a List<T>.Enumerator struct, this is fine.

Further to this, there are a number of classes in KSP that implement IEnumerable because they contain a standard collection type.  In the case of EditorPartListFilterList<T>, the GetEnumerator function is "correctly" declared as returning a  List<EditorPartListFilter<T>>.Enumerator struct so using foreach on it will not create garbage (with a decent compiler).  However, lots of the other classes declare GetEnumerator as returning an IEnumerator.  This is unfortunate as this is an interface, which follows the rules for classes and is allocated on the heap, so using foreach on these will create garbage, even with the very latest compilers.  The classes affected are:

  • ShipConstruct
  • BaseFieldList
  • PartModuleList
  • PartResourceList
  • PartResourceDefinitionList
  • RUI.Algorithms.Graph<T>
  • RUI.Algorithms.GraphList<T>

Note, while using foreach on these now does create garbage, they will almost certainly be fixed in the code cleanup for 1.2.

The VesselCrewManifest class is a bit of a strange case, it declares GetEnumerator "correctly" as returning a  List<PartCrewManifest>.Enumerator, but using foreach on it still generates a considerable amount of garbage, as does calling any of the public functions in the class.  It turns out there isn't any useful way to use this class without generating large amounts of garbage but, again, this will almost certainly be fixed in 1.2 (though the interface to the class may need to change).

Link to comment
Share on other sites

This thread is quite old. Please consider starting a new thread rather than reviving this one.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...