List Clear+Remove#9540
Conversation
| if (_size > 0) | ||
| public void Clear() | ||
| { | ||
| if (JitHelpers.ContainsReferences<T>() && _size > 0) |
There was a problem hiding this comment.
There are other places in this file that call Array.Clear. We should fix them all.
Right. Array.Copy is just fine for these (until we get optimized Span). |
|
Tail calls into Array.Copy for reference based Clears Marking List`1:Clear():this as NOINLINE because of unprofitable inline
Successfully inlined JitHelpers:ContainsReferences():bool (2 IL bytes) (depth 1) [below ALWAYS_INLINE size]
**************** Inline Tree
Inlines into 060034D8 List`1:Clear():this
[1 IL=0000 TR=000001 06003B02] [below ALWAYS_INLINE size] JitHelpers:ContainsReferences():bool
[0 IL=0047 TR=000087 06000248] [FAILED: noinline per IL/cached result] Array:Clear(ref,int,int)
Budget: initialTime=285, finalTime=275, initialBudget=2850, currentBudget=2850
Budget: initialSize=1841, finalSize=1841
; Assembly listing for method List`1:Clear():this
; Emitting BLENDED_CODE for X64 CPU with SSE2
; optimized code
; rsp based frame
; fully interruptible
; Final local variable assignments
;
; V00 this [V00,T00] ( 13, 12 ) ref -> rsi this
; V01 loc0 [V01,T01] ( 5, 4 ) int -> r8
;* V02 tmp0 [V02,T02] ( 0, 0 ) long -> zero-ref
;* V03 tmp1 [V03,T03] ( 0, 0 ) long -> zero-ref
; V04 OutArgs [V04 ] ( 1, 1 ) lclBlk (32) [rsp+0x00]
;
; Lcl frame size = 48
G_M58440_IG01:
56 push rsi
4883EC30 sub rsp, 48
48894C2428 mov qword ptr [rsp+28H], rcx
488BF1 mov rsi, rcx
G_M58440_IG02:
488B0E mov rcx, qword ptr [rsi]
448B4618 mov r8d, dword ptr [rsi+24]
33C9 xor ecx, ecx
894E18 mov dword ptr [rsi+24], ecx
FF461C inc dword ptr [rsi+28]
4585C0 test r8d, r8d
7E15 jle SHORT G_M58440_IG04
488B4E08 mov rcx, gword ptr [rsi+8]
33D2 xor edx, edx
488D0500000000 lea rax, [(reloc)]
G_M58440_IG03:
4883C430 add rsp, 48
5E pop rsi
48FFE0 rex.jmp rax
G_M58440_IG04:
4883C430 add rsp, 48
5E pop rsi
C3 ret
; Total bytes of code 60, prolog size 13 for method List`1:Clear():this |
|
@stephentoub @jkotas should arraypool clear anyway using this test when |
You mean, if T is or contains refs, clear the array even if it wasn't requested, so as to avoid keeping objects alive? On the one hand, I can see the benefit in some cases; however I know there are cases (because I've done it) where code explicitly clears the used portion itself and then specifies clearArray==false, in which case the change would add cost for no benefit. |
Ah, makes sense |
|
@jkotas added the other Array.Clears The remaining ones in coreclr are ArrayPool; definite reference types (ArrayList); definite value types (Streams) so assume is conscious decision. There is also Dictionary; but that has an array of Looking for |
|
Remaining |
|
👍 👍 👍 |
* List Clear+Remove * Tail call Array.Clear
* List Clear+Remove * Tail call Array.Clear Commit migrated from dotnet/coreclr@d400876
List Clear is warmspot in Kestrel
Struct based Clear trims to
Shame about the no-inline...
For remove I was looking to swap
Array.CopyforBuffer.Memmoveor similar, however the Span code for getting a pointer to aT[]element in an array is a little exotic