From 5622a14a7a036ab36e28963a4fba826a5ac798a7 Mon Sep 17 00:00:00 2001
From: Matthew Pickering <matthewtpickering@gmail.com>
Date: Mon, 3 Feb 2025 15:11:35 +0000
Subject: [PATCH] perf: nameToCLabel: Directly manipulate ByteString rather
 than going via strings

`nameToCLabel` is called from `lookupHsSymbol` many times during
bytecode linking. We can save a lot of allocations and time by directly
manipulating the bytestrings rather than going via intermediate lists.

Before: 2GB allocation, 1.11s
After: 260MB allocation, 375ms

Fixes #25719

-------------------------
Metric Decrease:
    MultiLayerModulesTH_OneShot
-------------------------
---
 compiler/GHC/ByteCode/Linker.hs | 18 +++++++++++-------
 1 file changed, 11 insertions(+), 7 deletions(-)

diff --git a/compiler/GHC/ByteCode/Linker.hs b/compiler/GHC/ByteCode/Linker.hs
index b81d8a15157..26a650fe72d 100644
--- a/compiler/GHC/ByteCode/Linker.hs
+++ b/compiler/GHC/ByteCode/Linker.hs
@@ -1,6 +1,7 @@
 {-# LANGUAGE FlexibleInstances     #-}
 {-# LANGUAGE MagicHash             #-}
 {-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE OverloadedStrings     #-}
 {-# OPTIONS_GHC -optc-DNON_POSIX_SOURCE #-}
 --
 --  (c) The University of Glasgow 2002-2006
@@ -210,9 +211,9 @@ linkFail who what
 
 
 nameToCLabel :: Name -> String -> FastString
-nameToCLabel n suffix = mkFastString label
+nameToCLabel n suffix = mkFastStringByteString label
   where
-    encodeZ = zString . zEncodeFS
+    encodeZ = fastZStringToByteString . zEncodeFS
     (Module pkgKey modName) = assert (isExternalName n) $ case nameModule n of
         -- Primops are exported from GHC.Prim, their HValues live in GHC.PrimopWrappers
         -- See Note [Primop wrappers] in GHC.Builtin.PrimOps.
@@ -222,11 +223,14 @@ nameToCLabel n suffix = mkFastString label
     modulePart  = encodeZ (moduleNameFS modName)
     occPart     = encodeZ $ occNameMangledFS (nameOccName n)
 
-    label = concat
-        [ if pkgKey == mainUnit then "" else packagePart ++ "_"
-        , modulePart
-        , '_':occPart
-        , '_':suffix
+    label = mconcat $
+        [ packagePart `mappend` "_" | pkgKey /= mainUnit ]
+        ++
+        [modulePart
+        , "_"
+        , occPart
+        , "_"
+        , fromString suffix
         ]
 
 
-- 
GitLab