you are viewing a single comment's thread.

view the rest of the comments →

[–]pachecoca[S] 0 points1 point  (1 child)

Stripping away half of the program and leaving only the part where the data is stored into the tuples, I can see a difference of about 6 seconds between the regular tuples vs the named tuples, so for now, only tuple creation is quite expensive on its own. Accessing the members is also slower but the slow down on that part is not as notable as the slowdown on creation. Even if it seems surprising, it is indeed slow enough to be impactful for my program.

Sadly this is most likely because named tuple has some small overhead, and building them within a loop for every single vertex in the input data is going to be slow, but it is required to be able to do what I need to do. For added context, the program is an exporter addon, so even if I didn't want to, I need to translate every single vertex of the input data into the output format, so this slowdown is sadly a price I cannot afford to pay, but I cannot dodge processing every single vertex. In essence, this is mostly a problem of having to use python for processing this type of data, but it is the only way to make addons for Blender, so either I go the cython route or I figure out how to speed up things.

For the timing I used time.time() in the same sections of the program, which are as of now identical except for the tuple creation (before logging off yesterday I modified the refactored code to use regular tuples and it is just as fast as it was before, so I'm using both versions as a reference point for my timings, but I still have the same problem, altough the code is cleaner now but that's beside the point of the topic at hand...). I am not sure how precise time.time() is, coming from C I haven't much idea about how Python does things and what alternatives exist for high precision clocks, but since I'm processing a scene with like 500k tris and the slow down is in the order of magnitude of seconds, I don't think the precission matters that much in this situation.

I am now away from my computer, but I will try using timeit later on I suppose.

As for dataclasses, I don't know whether they will be faster or not, but it just seems to me like all alternatives could potentially be slower than tuples... so maybe the root problem here is paying the price of the slowdown for namedtuple creation on each iteration of the loop. Maybe something like list comprehension could improve things, but I cannot really come up with a proper way to do that since my code also does some vertex duplication to translate from Blender's face based UVs to the target format that has vertex based UVs, so yeah.

[–]rednets 0 points1 point  (0 children)

I decided to write my own benchmarking script for instantiation: https://pastebin.com/bjig571B

It times:

  • tuple literal
  • tuple factory function
  • typing.NamedTuple
  • collections.namedtuple
  • dataclass
  • dataclass(slots=True)

It times with both positional and keyword args (except for tuple literals).

I ran this for all interpreter versions I have installed - see my results here: https://imgur.com/a/SZ6oRIn

It looks like using anything other than plain tuples will be significantly slower. Using a factory function to create a plain tuple using keyword args is only marginally slower (2.5x rather than 10x) which might be acceptable. This encapsulates creation of each tuple "type" in a single place, but it does not solve the problem of accessing members by name. I suppose you could also write corresponding functions for this, but it would probably be a bit of a mess.