Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Jan 10, 2026

Optimize genericAssign with code specialization

Similar to how genericReset was optimized in ccgreset.nim, this PR implements compile-time code specialization for genericAssign to dramatically improve performance.

Plan:

  • Create ccgassign.nim with specializeAssign implementation similar to ccgreset.nim
  • Integrate specializeAssign into ccgexprs.nim to replace genericAssign runtime calls
  • Handle all type cases (objects, tuples, arrays, sequences, strings, refs, etc.)
  • Handle case objects correctly (as mentioned in issue comments)
  • Add tests to verify correctness
  • Run existing assignment tests to ensure no regressions
  • Test with complex types and nested structures
Original prompt

This section details on the original issue you should resolve

<issue_title>genericAssign ridiculously slow</issue_title>
<issue_description>Just like genericReset is painfully slow (#13879 ), genericAssign causes ridiculous slowdowns in production code - replacing it with a homespun version can easily improve performance by orders of magnitude - here's one such implementation that's maybe 20 lines of effective code, that could remove the whole genericAssign codegen and speed things up significantly:

https://github.com/status-im/nimbus-eth2/blob/dba39c54d9bb3ded5f624ce026345c3a72f658dd/beacon_chain/spec/datatypes.nim#L809

func assign*[T](tgt: var T, src: T) =
  when supportsCopyMem(T):
    when sizeof(src) <= sizeof(int):
      tgt = src
    else:
      copyMem(addr tgt, unsafeAddr src, sizeof(tgt))
  elif T is object|tuple:
    for t, s in fields(tgt, src):
      when supportsCopyMem(type s) and sizeof(s) <= sizeof(int) * 2:
        t = s # Shortcut
      else:
        assign(t, s)
  elif isDistinct(T):
    assign(distinctBase tgt, distinctBase src)
  elif T is seq:
    tgt.setLen(src.len)
    when supportsCopyMem(type(tgt[0])):
      if tgt.len > 0:
        copyMem(addr tgt[0], unsafeAddr src[0], sizeof(tgt[0]) * tgt.len)
    else:
      for i in 0..<tgt.len:
        assign(tgt[i], src[i])
  elif T is ref:
    tgt = src
  else:
    unsupported T

status-im/nimbus-eth2#1166 shows some example performance improvements when using the new assign version - it's a bit annoying to implement because of how distinctBase can't be used with non-distinct types and there's no easy way to find if a type is distinct or not.
</issue_description>

Comments on the Issue (you are @copilot in this section)

@Araq There might be problems for assignment specialization when it comes to ``case`` objects. Would it be acceptable if these remain slow? @timotheecour > There might be problems for assignment specialization when it comes to case objects. Would it be acceptable if these remain slow?

can't the same approach as #14694 be used for case objects? seems like a similar problem as for this PR</comment_new>


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

genericAssign ridiculously slow

2 participants