Jump to content

Is 512 Persistent Actor References Bad?


doticu

Recommended Posts

"When any variable in a currently loaded script points at a reference, that reference is temporarily persistent. It will stay persistent until no variables are pointing at it any more..."

https://www.creationkit.com/index.php?title=Persistence_(Papyrus)#Variables

 

I'm keeping an always loaded, potentially full static Actor array with a length of 512. How bad is this on game performance? Is it a bad idea to make 512 actors persistent for a potentially long time?

 

If it is bad, is there a way to get all instances of Actor during run time from the actor base form id?

Edited by doticu
Link to comment
Share on other sites

  • 2 weeks later...

I'd say its definitely very bad, especially with actors.

 

Even if your machine copes okay, just think what would happen if several other mods were doing the same thing?

 

I'm no script guru but if you tell me why you're trying to do it and what you're trying to achieve I may be able to point you in a better direction...

 

Bethesda use aliases for things like the civil war battles and force the actors into the aliases only when required, for instance.

 

They don't try to force that many at once, even then. They rather cleverly just respawn the same actors out of sight of the player to give the

 

illusion of a much bigger fight.

Link to comment
Share on other sites

I'd say its definitely very bad, especially with actors.

 

Even if your machine copes okay, just think what would happen if several other mods were doing the same thing?

 

I'm no script guru but if you tell me why you're trying to do it and what you're trying to achieve I may be able to point you in a better direction...

 

Bethesda use aliases for things like the civil war battles and force the actors into the aliases only when required, for instance.

 

They don't try to force that many at once, even then. They rather cleverly just respawn the same actors out of sight of the player to give the

 

illusion of a much bigger fight.

 

Thanks for the response! I'm trying to track up to 512 actor instances in game, so they can be summoned by the user at any time, from anywhere. I'm keeping an array of Actor object pointers in order to do that. According to the wiki, that makes the objects have the "persistent" flag.

 

Now here's the problem. I don't know exactly what the persistent flag means to the game engine. It could simply mean that the engine keeps the object representation of the Actor in memory (as opposed to freeing that memory until the object is needed again.) And that's totally okay. I doubt 512 actor objects take up as much room as a single 2048 texture does. But it could mean more than that, e.g. in the game loop the object's AI is updated even when not being rendered, thus it may be causing unnecessary computations for what I require.

 

Now I can say for a fact that keeping an Actor object persistent does not cause the engine to render its 3D when it's not in a loaded cell. I'm currently tracking 160+ npcs in my current playthrough and I haven't noticed any slowdown on my low-end PC. This is nothing like a civil war battle where the npcs must be rendered at the same time. In fact, none of the 512 npcs have to be rendered all the time, only when the user calls for one before sending them away again.

 

As regards to aliasing, if I understand it correctly, it doesn't make a difference whether or not I alias or reference the Actor object directly, both are made persistent until the variable holding them is set to none.

 

I guess what I'm worried about is the game loop running through the 512 npcs and needlessly updating their objects when it may be unnecessary. I'm looking for options without lowering the 512 figure. I'm willing to take another hit of indirection to keep them unloaded if it turns out it's bad on performance. If I can take an Actor instance, get its form id as a string, and then convert that string back to the Actor instance, that would solve the problem. But I don't know how to do that, or if it's possible, or if it's safe, or if the npc will still be summonable. An alternative would be to simply disable the npc's AI until they are loaded, if that is what the issue is. But again I don't know, so if any expert on the engine could answer the question "what exactly does the persistent flag mean?", it would be a big help.

Edited by doticu
Link to comment
Share on other sites

Good question, hopefully someone can enlighten both of us a bit more. How much work is it to simply do it and test?

https://github.com/xanderdunn/skaar/wiki/Understanding-Forms%2C-Object-References%2C-Reference-Aliases%2C-and-Persistence

 

That page seems to states that all things like "packages, script properties etcetera" will remain loaded when the objects are persistent.

 

I have no idea if each of your actors will constantly update packages.

 

I've probably been doing the same searches as you and am coming up with confusion everywhere on the subject.

 

Seems like a test's the best way forward!

 

 

Link to comment
Share on other sites

Good question, hopefully someone can enlighten both of us a bit more. How much work is it to simply do it and test?

 

https://github.com/xanderdunn/skaar/wiki/Understanding-Forms%2C-Object-References%2C-Reference-Aliases%2C-and-Persistence

 

That page seems to states that all things like "packages, script properties etcetera" will remain loaded when the objects are persistent.

 

I have no idea if each of your actors will constantly update packages.

 

I've probably been doing the same searches as you and am coming up with confusion everywhere on the subject.

 

Seems like a test's the best way forward!

 

 

 

Thank you for looking into this! The article you linked to is pretty interesting. If I'm understanding it correctly, the point of persistence is to have an object instance keep the same reference id it was spawned with, so that its state can be transferred and interacted with between save games, and for this reason it is stored in RAM during game time, and the save file afterwards. Now something interesting: whenever an Actor that has the unique flag is placed in a cell in the Creation Kit, it is given a unique reference id which is baked into the .esp file and thus never changes. In fact, this UESP article even points out that many npcs are referenced like this in vanilla quests, so the reference id must not change. Every save game has the same reference id for every unique npc. And since I'm mostly interested in storing only unique Actors in my array (at this time), it would seem that all the npcs I'm storing are actually already persistent and this is a non-issue.

 

However, I'm not completely certain that they are really considered persistent and whether or not I'd be causing save file bloat. But I do know that I can store just the form id for a unique Actor with GetFormID() instead of keeping the Actor instance itself, and with certainty I know that the Actor will use that same id from save game to save game, so it's safe. In the console all I need do to get the Actor is use the prid command along with the reference id, but in papyrus I have no idea how to use that int to get the reference.

 

EDIT: It would appear that this SKSE plugin "ConsoleUtilSSE" is capable of getting me the Actor reference like so:

int myActorRefId; previously returned by myActorRef.GetFormID()
ConsoleUtil.ExecuteCommand("prid " + myActorRefId as string)
Actor myActorRef = ConsoleUtil.GetSelectedReference() as Actor

I'm not sure at this time if it is worth adding ConsoleUtilSSE as a dependency, because it may very well be the case that this is a non-issue with unique NPCs. Also I'd rather use either a native papyrus function or an SKSE function if anyone knows one. But it does seem possible now, and quite safe indeed! As long as the NPC is unique, that is. Thank you for your time and thoughts cumbrianlad.

 

The next big question is "are unique NPC instances necessarily persistent?"

Edited by doticu
Link to comment
Share on other sites

It's been a good little debate.

Here's something else maybe worth keeping in mind.

I read somewhere ages ago to avoid selecting forced reference type aliases (specific reference), in case it made them persistent even after the quest stopped running. Better to choose unique actors etc.
That made me think (for once :thumbsup:). Using a unique actor alias reference you should set a persist location to the actor (usually the location their editor location is). If you don't, their alias may not fill.
I looked at a mod I'm doing for Skyhaven temple and checked my unique actors (a load of craftsmen working out of a new workshop in Markarth). They all have persist locations set but none of them
are flagged in SSEedit as persistent. (None of them have scripts attached, though. That would be an interesting experiment)

I'm guessing that's why it's better to select them as unique actors rather than forced references. Since assigning a persist location to an object doesn't make it persistent, those references will only be persistent when the quest is running.

Having said all that, the thread below has a person who doesn't believe 5000 persistent references in a mod is too much!
https://forums.nexusmods.com/index.php?/topic/1222421-creation-kit-persistence/

 

Maybe we're both just being too cautious!

 

I'm afraid I don't have a clue about the consoleutil question.

 

P.S. in the thread above, someone quotes the creation kit website stating that unique NPCs are always persistent! I can't see that being the case, if my actors are flagged as temporary in SSEedit.

Link to comment
Share on other sites

It's been a good little debate.

 

Here's something else maybe worth keeping in mind.

 

I read somewhere ages ago to avoid selecting forced reference type aliases (specific reference), in case it made them persistent even after the quest stopped running. Better to choose unique actors etc.

That made me think (for once :thumbsup:). Using a unique actor alias reference you should set a persist location to the actor (usually the location their editor location is). If you don't, their alias may not fill.

I looked at a mod I'm doing for Skyhaven temple and checked my unique actors (a load of craftsmen working out of a new workshop in Markarth). They all have persist locations set but none of them

are flagged in SSEedit as persistent. (None of them have scripts attached, though. That would be an interesting experiment)

 

I'm guessing that's why it's better to select them as unique actors rather than forced references. Since assigning a persist location to an object doesn't make it persistent, those references will only be persistent when the quest is running.

 

Having said all that, the thread below has a person who doesn't believe 5000 persistent references in a mod is too much!

https://forums.nexusmods.com/index.php?/topic/1222421-creation-kit-persistence/

 

Maybe we're both just being too cautious!

 

I'm afraid I don't have a clue about the consoleutil question.

 

P.S. in the thread above, someone quotes the creation kit website stating that unique NPCs are always persistent! I can't see that being the case, if my actors are flagged as temporary in SSEedit.

 

That thread is a great find, thank you! The guy who doesn't believe 5000 persistent refs is a problem mentioned his "musuem mod." That's the guy who did Legacy of the Dragonborn! I can't imagine a mod that would give us better test results among users than that one, because so many people have used it. He mentioned that the main problem was one of save bloat (and of course that means more RAM usage.) Now I do recall that I had to allocate more available RAM for Skyrim after using his mod, and I suspected it was more than just a texture issue, and it makes a lot of sense to me now I know he uses a lot of persistent references.

 

That quote that another user brought up about persistent references taking computation time when they are unloaded, I don't consider true, as it doesn't match my experience with LOTD. LOTD causes a big hit on my system because I have limited RAM and VRAM, so I know when I have one of its museum cells still loaded in the cell buffer. However, when the cell is not in the buffer, the game tends to run more smoothly. So I'm thinking the danger of diminishing performance actually comes from having too many persistent objects in the game session at once, as it consumes RAM.

 

Now in his case, the persistent references are all made statically in the creation kit, whereas in my case npcs may potentially be made persistent dynamically. I understand you brought up that another risk is that dynamic (that is temporary) persistent objects may possibly never be removed from the save file. This can be caused by any number of things, such as not setting a variable to none, or the quest referencing that object was not killed properly. It's possible there may be a misunderstanding among developers that some objects are already persistent statically and thus cannot be made unpersistent (such as with every property added to a quest.)

 

With this all in mind, I think that the performance hit for having an array of objects that are either statically or dynamically persistent in a never-ending quest with assured usage of none to delete from the array, is next to none, when near or under the limit of 512 Actor objects.

 

However a couple thousand would be more concerning, and this may be one of the key reasons why the base game has such a limited amount of unique npcs.

Edited by doticu
Link to comment
Share on other sites

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...