Issue 24700 - MsCoffObj_getsegment is really slow O(n^2)
Summary: MsCoffObj_getsegment is really slow O(n^2)
Status: NEW
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: x86 Windows
: P1 normal
Assignee: No Owner
URL:
Keywords: industry
Depends on:
Blocks:
 
Reported: 2024-08-13 11:00 UTC by Dennis
Modified: 2024-11-16 23:27 UTC (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Dennis 2024-08-13 11:00:50 UTC
Code generation of an internal dub project at SARC takes way longer than necessary:

objflush_pointerRefs is called on an .obj file with ~4600 000 pointer refs.
This calls MsCoffObj_getsegment(".dp$B") for each of them, which does a linear scan over all sections:

```
for (segidx_t seg = 1; seg < SegData.length; seg++)
{
     if (strcmp(...))
         ...       
```

https://github.com/dlang/dmd/blob/05b2c0dfe27f0797151e7c6f7c7db43f700c1edc/compiler/src/dmd/backend/mscoffobj.d#L1364

SegData.length is 61000 here.

ElfObj_getsegment uses a hash table for this, MsCoff_getsegment should do this as well.
Comment 1 Dennis 2024-08-13 12:27:13 UTC
N.b. even a dumb patch like this would mostly fix it, since it's trying to get the same section over and over:
```
--- a/compiler/src/dmd/backend/mscoffobj.d
+++ b/compiler/src/dmd/backend/mscoffobj.d
@@ -1357,16 +1357,29 @@ int MsCoffObj_jmpTableSegment(Symbol *s)
 @trusted
 segidx_t MsCoffObj_getsegment(const(char)* sectname, uint flags)
 {
+    __gshared segidx_t lastFind = 1;
     //printf("getsegment(%s)\n", sectname);
     assert(strlen(sectname) <= 8);      // so it won't go into string_table
     if (!(flags & IMAGE_SCN_LNK_COMDAT))
     {
+        if (lastFind < SegData.length)
+        {
+            seg_data *pseg = SegData[lastFind];
+            if (!(ScnhdrTab[pseg.SDshtidx].Characteristics & IMAGE_SCN_LNK_COMDAT) &&
+                strncmp(cast(const(char)* )ScnhdrTab[pseg.SDshtidx].Name, sectname, 8) == 0)
+            {
+                //printf("\t%s\n", sectname);
+                return lastFind;         // return existing segment
+            }
+        }
+
         for (segidx_t seg = 1; seg < SegData.length; seg++)
         {   seg_data *pseg = SegData[seg];
             if (!(ScnhdrTab[pseg.SDshtidx].Characteristics & IMAGE_SCN_LNK_COMDAT) &&
                 strncmp(cast(const(char)* )ScnhdrTab[pseg.SDshtidx].Name, sectname, 8) == 0)
             {
                 //printf("\t%s\n", sectname);
+                lastFind = seg;
                 return seg;         // return existing segment
             }
         }
```
Comment 2 Dennis 2024-08-13 14:16:17 UTC
Here's a test case to artificially produce similar Symbol / pointer ref counts:

```
static foreach (i; 0 .. 8_000)
{
    mixin("struct S"~i.stringof~" {float x;}");
}

__gshared int*[64_000] x;
```

Compile times goes from 35.5s => 2.4s after applying the patch I mentioned.
Comment 3 Dlang Bot 2024-08-13 14:43:13 UTC
@dkorpel created dlang/dmd pull request #16780 "Bugzilla 24700 - Don't search for mscoff .dp$B section over and over" mentioning this issue:

- Bugzilla 24700 - Don't search for mscoff .dp$B section over and over

https://github.com/dlang/dmd/pull/16780
Comment 4 Dlang Bot 2024-08-14 09:21:24 UTC
dlang/dmd pull request #16780 "Bugzilla 24700 - Don't search for mscoff .dp$B section over and over" was merged into master:

- 23d0c3dbf140ab6eb3ffa82dfddba03ac19b4861 by Dennis Korpel:
  Bugzilla 24700 - Don't search for mscoff .dp$B section over and over

https://github.com/dlang/dmd/pull/16780
Comment 5 Dlang Bot 2024-10-24 23:05:15 UTC
@veelo created dlang/dmd pull request #17029 "Bugzilla 24700 - Don't search for mscoff .dp$B section over and over …" mentioning this issue:

- Bugzilla 24700 - Don't search for mscoff .dp$B section over and over (#16780)
  
  (cherry picked from commit 67227f03e04368654d40ff707be7ee424b490e3b)

https://github.com/dlang/dmd/pull/17029
Comment 6 Dlang Bot 2024-10-25 01:07:00 UTC
dlang/dmd pull request #17029 "Bugzilla 24700 - Don't search for mscoff .dp$B section over and over …" was merged into stable:

- 36b6061ce0c0fc1bd5497b1d83e30fb5215b2e2c by Dennis:
  Bugzilla 24700 - Don't search for mscoff .dp$B section over and over (#16780)
  
  (cherry picked from commit 67227f03e04368654d40ff707be7ee424b490e3b)

https://github.com/dlang/dmd/pull/17029
Comment 7 Dlang Bot 2024-11-16 15:12:28 UTC
@kinke created dlang/dmd pull request #17069 "Merge stable" mentioning this issue:

- Bugzilla 24700 - Don't search for mscoff .dp$B section over and over (#16780)
  
  (cherry picked from commit 67227f03e04368654d40ff707be7ee424b490e3b)

https://github.com/dlang/dmd/pull/17069
Comment 8 Dlang Bot 2024-11-16 23:27:11 UTC
dlang/dmd pull request #17069 "Merge stable" was merged into master:

- 2a63416b43cdf876e8818501f56a4ec441f053bf by Dennis:
  Bugzilla 24700 - Don't search for mscoff .dp$B section over and over (#16780)
  
  (cherry picked from commit 67227f03e04368654d40ff707be7ee424b490e3b)

https://github.com/dlang/dmd/pull/17069