From 3e2ccc0842ce57131939cab7eda32a8c9b5a1251 Mon Sep 17 00:00:00 2001
From: Moritz Kiefer
Date: Mon, 19 Aug 2019 20:15:13 +0200
Subject: [PATCH] Switch to a streaming zip encoding (#2595)
This switches the creation of the archive in `daml build` from
`zip-archive` to `zip`. This has a few advantages:
1. It gets rid of lazy IO for reading all the interface and source
files. This avoids the high usage of file handles in `daml build`.
2. It seems to be a slight improvement in max memory usage and runtime
and a giant improvement in allocations (but I think the latter
probably comes primarily from the fact that the locations are moved to
the bzip C library). The improvement in max memory usage is less than
I expected so probably there is still something off somewhere.
For now, I only switched over `createArchive`. Archive reading is
still done using `zip-archive`. We might want to switch that over in a
separate PR.
---
3rdparty/c/bzip2.BUILD | 24 ++++++
3rdparty/haskell/BUILD.bindings-DSL | 18 +++++
3rdparty/haskell/bzlib-conduit.patch | 13 ++++
WORKSPACE | 17 +++++
.../daml-lf-reader/src/DA/Daml/LF/Reader.hs | 2 +-
compiler/damlc/BUILD.bazel | 1 +
compiler/damlc/daml-compiler/BUILD.bazel | 3 +-
.../daml-compiler/src/DA/Daml/Compiler/Dar.hs | 51 ++++++-------
compiler/damlc/lib/DA/Cli/Damlc.hs | 75 ++++++++++---------
compiler/damlc/lib/DA/Cli/Visual.hs | 2 +-
deps.bzl | 9 +++
unreleased.rst | 2 +
12 files changed, 147 insertions(+), 70 deletions(-)
create mode 100644 3rdparty/c/bzip2.BUILD
create mode 100644 3rdparty/haskell/BUILD.bindings-DSL
create mode 100644 3rdparty/haskell/bzlib-conduit.patch
diff --git a/3rdparty/c/bzip2.BUILD b/3rdparty/c/bzip2.BUILD
new file mode 100644
index 000000000000..056fafaa68c4
--- /dev/null
+++ b/3rdparty/c/bzip2.BUILD
@@ -0,0 +1,24 @@
+package(default_visibility = ["//visibility:public"])
+
+cc_library(
+ name = "bz2",
+ srcs = [
+ "blocksort.c",
+ "bzlib.c",
+ "compress.c",
+ "crctable.c",
+ "decompress.c",
+ "huffman.c",
+ "randtable.c",
+ ],
+ hdrs = [
+ "bzlib.h",
+ "bzlib_private.h",
+ ],
+ includes = [
+ ".",
+ ],
+ visibility = [
+ "//visibility:public",
+ ],
+)
diff --git a/3rdparty/haskell/BUILD.bindings-DSL b/3rdparty/haskell/BUILD.bindings-DSL
new file mode 100644
index 000000000000..fd534cbd4570
--- /dev/null
+++ b/3rdparty/haskell/BUILD.bindings-DSL
@@ -0,0 +1,18 @@
+package(default_visibility = ["//visibility:public"])
+
+load("@rules_haskell//haskell:defs.bzl", "haskell_library")
+load("@ai_formation_hazel//:hazel.bzl", "hazel_library")
+
+haskell_library(
+ name = "lib",
+ visibility = ["//visibility:public"],
+ srcs = [":Bindings/Utilities.hs"],
+ deps = [hazel_library("base"), ":bindings-DSL-cbits"],
+)
+
+
+cc_library(
+ name = "bindings-DSL-cbits",
+ visibility = ["//visibility:public"],
+ hdrs = [":bindings.dsl.h", ":bindings.cmacros.h"],
+)
diff --git a/3rdparty/haskell/bzlib-conduit.patch b/3rdparty/haskell/bzlib-conduit.patch
new file mode 100644
index 000000000000..26f168ec62aa
--- /dev/null
+++ b/3rdparty/haskell/bzlib-conduit.patch
@@ -0,0 +1,13 @@
+diff --git a/src/Data/Conduit/BZlib/Internal.hsc b/src/Data/Conduit/BZlib/Internal.hsc
+index f980d35..18d6e3a 100644
+--- a/src/Data/Conduit/BZlib/Internal.hsc
++++ b/src/Data/Conduit/BZlib/Internal.hsc
+@@ -1,7 +1,7 @@
+ {-# LANGUAGE ForeignFunctionInterface #-}
+
+ #include
+-#include
++#include "bindings.dsl.h"
+
+ module Data.Conduit.BZlib.Internal where
+
diff --git a/WORKSPACE b/WORKSPACE
index da0676fd6bd0..e810819f394b 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -494,6 +494,7 @@ hazel_repositories(
},
),
exclude_packages = [
+ "bindings-DSL",
"clock",
# Excluded since we build it via the http_archive line above.
"ghc-lib-parser",
@@ -515,6 +516,7 @@ hazel_repositories(
{
"z": "@com_github_madler_zlib//:z",
"ffi": "" if is_windows else "@libffi_nix//:ffi",
+ "bz2": "@bzip2//:bz2",
},
),
ghc_workspaces = {
@@ -586,6 +588,12 @@ hazel_repositories(
"91dd121ac565009f2fc215c50f3365ed66705071a698a545e869041b5d7ff4da",
patch_args = ["-p1"],
patches = ["@com_github_digital_asset_daml//bazel_tools:haskell-c2hs.patch"],
+ ) + hazel_hackage(
+ "bzlib-conduit",
+ "0.3.0.2",
+ "eb2c732b3d4ab5f7b367c51eef845e597ade19da52c03ee11954d35b6cfc4128",
+ patch_args = ["-p1"],
+ patches = ["@com_github_digital_asset_daml//3rdparty/haskell:bzlib-conduit.patch"],
),
pkgs = packages,
),
@@ -611,6 +619,15 @@ hazel_custom_package_hackage(
version = "0.6.2",
)
+hazel_custom_package_hackage(
+ package_name = "bindings-DSL",
+ # Without a custom build file, packages depending on bindings-DSL
+ # fail to find bindings.dsl.h.
+ build_file = "//3rdparty/haskell:BUILD.bindings-DSL",
+ sha256 = "63de32380c68d1cc5e9c7b3622d67832c786da21163ba0c8a4835e6dd169194f",
+ version = "1.0.25",
+)
+
hazel_custom_package_hackage(
package_name = "streaming-commons",
build_file = "//3rdparty/haskell:BUILD.streaming-commons",
diff --git a/compiler/daml-lf-reader/src/DA/Daml/LF/Reader.hs b/compiler/daml-lf-reader/src/DA/Daml/LF/Reader.hs
index 1185d8ca45bd..5ad9df663df0 100644
--- a/compiler/daml-lf-reader/src/DA/Daml/LF/Reader.hs
+++ b/compiler/daml-lf-reader/src/DA/Daml/LF/Reader.hs
@@ -9,7 +9,7 @@ module DA.Daml.LF.Reader
, getManifestField
) where
-import Codec.Archive.Zip
+import "zip-archive" Codec.Archive.Zip
import qualified Data.ByteString.Lazy as BSL
import qualified Data.ByteString.Lazy.UTF8 as UTF8
import qualified Data.ByteString.Char8 as BSC
diff --git a/compiler/damlc/BUILD.bazel b/compiler/damlc/BUILD.bazel
index f6e7aee04897..5e23040aa495 100644
--- a/compiler/damlc/BUILD.bazel
+++ b/compiler/damlc/BUILD.bazel
@@ -120,6 +120,7 @@ da_haskell_library(
"vector",
"xml",
"yaml",
+ "zip",
"zip-archive",
"unordered-containers",
"uniplate",
diff --git a/compiler/damlc/daml-compiler/BUILD.bazel b/compiler/damlc/daml-compiler/BUILD.bazel
index 31ee7f7e20d0..f3609fe08f33 100644
--- a/compiler/damlc/daml-compiler/BUILD.bazel
+++ b/compiler/damlc/daml-compiler/BUILD.bazel
@@ -12,6 +12,7 @@ da_haskell_library(
hazel_deps = [
"base",
"bytestring",
+ "conduit",
"containers",
"directory",
"extra",
@@ -27,7 +28,7 @@ da_haskell_library(
"text",
"time",
"transformers",
- "zip-archive",
+ "zip",
],
src_strip_prefix = "src",
visibility = ["//visibility:public"],
diff --git a/compiler/damlc/daml-compiler/src/DA/Daml/Compiler/Dar.hs b/compiler/damlc/daml-compiler/src/DA/Daml/Compiler/Dar.hs
index 7a231af16f60..9d916f6abfe3 100644
--- a/compiler/damlc/daml-compiler/src/DA/Daml/Compiler/Dar.hs
+++ b/compiler/damlc/daml-compiler/src/DA/Daml/Compiler/Dar.hs
@@ -8,7 +8,7 @@ module DA.Daml.Compiler.Dar
, pkgNameVersion
) where
-import qualified Codec.Archive.Zip as Zip
+import qualified "zip" Codec.Archive.Zip as Zip
import Control.Monad.Extra
import Control.Monad.IO.Class
import Control.Monad.Trans.Maybe
@@ -18,6 +18,7 @@ import DA.Daml.Options.Types
import qualified Data.ByteString as BS
import qualified Data.ByteString.Lazy as BSL
import qualified Data.ByteString.Lazy.Char8 as BSC
+import Data.Conduit.Combinators (sourceFile, sourceLazy)
import Data.List.Extra
import qualified Data.Map.Strict as Map
import Data.Maybe
@@ -78,16 +79,15 @@ buildDar ::
-> PackageConfigFields
-> NormalizedFilePath
-> FromDalf
- -> IO (Maybe BSL.ByteString)
+ -> IO (Maybe (Zip.ZipArchive ()))
buildDar service pkgConf@PackageConfigFields {..} ifDir dalfInput = do
liftIO $
IdeLogger.logDebug (ideLogger service) $
"Creating dar: " <> T.pack pMain
if unFromDalf dalfInput
- then liftIO $
- Just <$> do
- bytes <- BSL.readFile pMain
- createArchive pkgConf "" bytes [] (toNormalizedFilePath ".") [] [] []
+ then do
+ bytes <- BSL.readFile pMain
+ pure $ Just $ createArchive pkgConf "" bytes [] (toNormalizedFilePath ".") [] [] []
else runAction service $
runMaybeT $ do
WhnfPackage pkg <- useE GeneratePackage file
@@ -118,7 +118,7 @@ buildDar service pkgConf@PackageConfigFields {..} ifDir dalfInput = do
fileDependencies <- MaybeT $ getDependencies file
let dataFiles =
[mkConfFile pkgConf pkgModuleNames (T.unpack pkgId)]
- liftIO $
+ pure $
createArchive
pkgConf
(T.unpack pkgId)
@@ -176,29 +176,21 @@ createArchive ::
-> [NormalizedFilePath] -- ^ Module dependencies
-> [(String, BS.ByteString)] -- ^ Data files
-> [NormalizedFilePath] -- ^ Interface files
- -> IO BSL.ByteString
+ -> Zip.ZipArchive ()
createArchive PackageConfigFields {..} pkgId dalf dalfDependencies srcRoot fileDependencies dataFiles ifaces
= do
-- Reads all module source files, and pairs paths (with changed prefix)
-- with contents as BS. The path must be within the module root path, and
-- is modified to have prefix instead of the original root path.
- srcFiles <-
- forM fileDependencies $ \mPath -> do
- contents <- BSL.readFile $ fromNormalizedFilePath mPath
- return
- ( pkgName
- fromNormalizedFilePath (makeRelative' srcRoot mPath)
- , contents)
- ifaceFaceFiles <-
- forM ifaces $ \mPath -> do
- contents <- BSL.readFile $ fromNormalizedFilePath mPath
- let ifaceRoot =
- toNormalizedFilePath
- (ifaceDir fromNormalizedFilePath srcRoot)
- return
- ( pkgName
- fromNormalizedFilePath (makeRelative' ifaceRoot mPath)
- , contents)
+ forM_ fileDependencies $ \mPath -> do
+ entry <- Zip.mkEntrySelector $ pkgName fromNormalizedFilePath (makeRelative' srcRoot mPath)
+ Zip.sinkEntry Zip.Deflate (sourceFile $ fromNormalizedFilePath mPath) entry
+ forM_ ifaces $ \mPath -> do
+ let ifaceRoot =
+ toNormalizedFilePath
+ (ifaceDir fromNormalizedFilePath srcRoot)
+ entry <- Zip.mkEntrySelector $ pkgName fromNormalizedFilePath (makeRelative' ifaceRoot mPath)
+ Zip.sinkEntry Zip.Deflate (sourceFile $ fromNormalizedFilePath mPath) entry
let dalfName = pkgName pkgNameVersion pName pVersion <.> "dalf"
let dependencies =
[ (pkgName T.unpack depName <> ".dalf", BSL.fromStrict bs)
@@ -213,11 +205,10 @@ createArchive PackageConfigFields {..} pkgId dalf dalfDependencies srcRoot fileD
( "META-INF/MANIFEST.MF"
, manifestHeader dalfName (dalfName : map fst dependencies)) :
(dalfName, dalf) :
- srcFiles ++ ifaceFaceFiles ++ dependencies ++ dataFiles'
- mkEntry (filePath, content) = Zip.toEntry filePath 0 content
- zipArchive =
- foldr (Zip.addEntryToArchive . mkEntry) Zip.emptyArchive allFiles
- pure $ Zip.fromArchive zipArchive
+ dependencies ++ dataFiles'
+ forM_ allFiles $ \(file, content) -> do
+ entry <- Zip.mkEntrySelector file
+ Zip.sinkEntry Zip.Deflate (sourceLazy content) entry
where
pkgName = fullPkgName pName pVersion pkgId
manifestHeader :: FilePath -> [String] -> BSL.ByteString
diff --git a/compiler/damlc/lib/DA/Cli/Damlc.hs b/compiler/damlc/lib/DA/Cli/Damlc.hs
index d18b0c23d8a7..739e7ebe70fa 100644
--- a/compiler/damlc/lib/DA/Cli/Damlc.hs
+++ b/compiler/damlc/lib/DA/Cli/Damlc.hs
@@ -7,7 +7,8 @@
-- | Main entry-point of the DAML compiler
module DA.Cli.Damlc (main) where
-import Codec.Archive.Zip
+import qualified "zip-archive" Codec.Archive.Zip as ZipArchive
+import qualified "zip" Codec.Archive.Zip as Zip
import Control.Exception
import Control.Exception.Safe (catchIO)
import Control.Monad.Except
@@ -415,37 +416,37 @@ createProjectPackageDb (AllowDifferentSdkVersions allowDiffSdkVersions) lfVersio
sdkVersions <-
forM fps0 $ \fp -> do
bs <- BSL.readFile fp
- let archive = toArchive bs
+ let archive = ZipArchive.toArchive bs
manifest <- getEntry "META-INF/MANIFEST.MF" archive
sdkVersion <- trim <$> getManifestFieldOrErr manifest "Sdk-Version"
let confFiles =
[ e
- | e <- zEntries archive
- , ".conf" `isExtensionOf` eRelativePath e
+ | e <- ZipArchive.zEntries archive
+ , ".conf" `isExtensionOf` ZipArchive.eRelativePath e
]
let dalfs =
[ e
- | e <- zEntries archive
- , ".dalf" `isExtensionOf` eRelativePath e
+ | e <- ZipArchive.zEntries archive
+ , ".dalf" `isExtensionOf` ZipArchive.eRelativePath e
]
let srcs =
[ e
- | e <- zEntries archive
- , takeExtension (eRelativePath e) `elem`
+ | e <- ZipArchive.zEntries archive
+ , takeExtension (ZipArchive.eRelativePath e) `elem`
[".daml", ".hie", ".hi"]
]
forM_ dalfs $ \dalf -> do
- let path = dbPath eRelativePath dalf
+ let path = dbPath ZipArchive.eRelativePath dalf
createDirectoryIfMissing True (takeDirectory path)
- BSL.writeFile path (fromEntry dalf)
+ BSL.writeFile path (ZipArchive.fromEntry dalf)
forM_ confFiles $ \conf ->
BSL.writeFile
(dbPath "package.conf.d"
- (takeFileName $ eRelativePath conf))
- (fromEntry conf)
+ (takeFileName $ ZipArchive.eRelativePath conf))
+ (ZipArchive.fromEntry conf)
forM_ srcs $ \src -> do
- let path = dbPath eRelativePath src
- write path (fromEntry src)
+ let path = dbPath ZipArchive.eRelativePath src
+ write path (ZipArchive.fromEntry src)
pure sdkVersion
let uniqSdkVersions = nubSort sdkVersions
-- if there are no package dependencies, sdkVersions will be empty
@@ -491,7 +492,7 @@ execBuild projectOpts options mbOutFile initPkgDb = withProjectRoot' projectOpts
dar <- mbErr "ERROR: Creation of DAR file failed." mbDar
let fp = targetFilePath $ pkgNameVersion pName pVersion
createDirectoryIfMissing True $ takeDirectory fp
- BSL.writeFile fp dar
+ Zip.createArchive fp dar
putStrLn $ "Created " <> fp <> "."
where
targetFilePath name = fromMaybe (distDir name <.> "dar") mbOutFile
@@ -546,7 +547,7 @@ execPackage projectOpts filePath opts mbOutFile dalfInput = withProjectRoot' pro
exitFailure
Just dar -> do
createDirectoryIfMissing True $ takeDirectory targetFilePath
- BSL.writeFile targetFilePath dar
+ Zip.createArchive targetFilePath dar
putStrLn $ "Created " <> targetFilePath <> "."
where
-- This is somewhat ugly but our CLI parser guarantees that this will always be present.
@@ -567,7 +568,7 @@ execPackage projectOpts filePath opts mbOutFile dalfInput = withProjectRoot' pro
execInspect :: FilePath -> FilePath -> Bool -> DA.Pretty.PrettyLevel -> Command
execInspect inFile outFile jsonOutput lvl = do
let mainDalf
- | "dar" `isExtensionOf` inFile = BSL.toStrict . mainDalfContent . manifestFromDar . toArchive . BSL.fromStrict
+ | "dar" `isExtensionOf` inFile = BSL.toStrict . mainDalfContent . manifestFromDar . ZipArchive.toArchive . BSL.fromStrict
| otherwise = id
bytes <- mainDalf <$> B.readFile inFile
@@ -596,21 +597,21 @@ execInspectDar inFile = do
bytes <- B.readFile inFile
putStrLn "DAR archive contains the following files: \n"
- let dar = toArchive $ BSL.fromStrict bytes
- let files = [eRelativePath e | e <- zEntries dar]
+ let dar = ZipArchive.toArchive $ BSL.fromStrict bytes
+ let files = [ZipArchive.eRelativePath e | e <- ZipArchive.zEntries dar]
mapM_ putStrLn files
putStrLn "\nDAR archive contains the following packages: \n"
let dalfEntries =
- [e | e <- zEntries dar, ".dalf" `isExtensionOf` eRelativePath e]
+ [e | e <- ZipArchive.zEntries dar, ".dalf" `isExtensionOf` ZipArchive.eRelativePath e]
forM_ dalfEntries $ \dalfEntry -> do
- let dalf = BSL.toStrict $ fromEntry dalfEntry
+ let dalf = BSL.toStrict $ ZipArchive.fromEntry dalfEntry
(pkgId, _lfPkg) <-
errorOnLeft
- ("Cannot decode package " <> eRelativePath dalfEntry)
+ ("Cannot decode package " <> ZipArchive.eRelativePath dalfEntry)
(Archive.decodeArchive dalf)
putStrLn $
- (dropExtension $ takeFileName $ eRelativePath dalfEntry) <> " " <>
+ (dropExtension $ takeFileName $ ZipArchive.eRelativePath dalfEntry) <> " " <>
show (LF.unPackageId pkgId)
execMigrate ::
@@ -694,12 +695,12 @@ execMigrate projectOpts opts0 inFile1_ inFile2_ mbDir = do
forM [inFile1, inFile2] $ \inFile -> do
bytes <- B.readFile inFile
let pkgName = takeBaseName inFile
- let dar = toArchive $ BSL.fromStrict bytes
+ let dar = ZipArchive.toArchive $ BSL.fromStrict bytes
-- get the main pkg
manifest <- getEntry "META-INF/MANIFEST.MF" dar
mainDalfPath <- getManifestFieldOrErr manifest "Main-Dalf"
mainDalfEntry <- getEntry mainDalfPath dar
- (mainPkgId, mainLfPkg) <- decode $ BSL.toStrict $ fromEntry mainDalfEntry
+ (mainPkgId, mainLfPkg) <- decode $ BSL.toStrict $ ZipArchive.fromEntry mainDalfEntry
pure (pkgName, mainPkgId, mainLfPkg)
-- generate upgrade modules and instances modules
let eqModNames =
@@ -751,13 +752,13 @@ execMigrate projectOpts opts0 inFile1_ inFile2_ mbDir = do
NM.lookup modName $ LF.packageModules pkg
-- | Get an entry from a dar or fail.
-getEntry :: FilePath -> Archive -> IO Entry
+getEntry :: FilePath -> ZipArchive.Archive -> IO ZipArchive.Entry
getEntry fp dar =
maybe (fail $ "Package does not contain " <> fp) pure $
- findEntryByPath fp dar
+ ZipArchive.findEntryByPath fp dar
-- | Parse a manifest field.
-getManifestFieldOrErr :: Entry -> String -> IO String
+getManifestFieldOrErr :: ZipArchive.Entry -> String -> IO String
getManifestFieldOrErr manifest field =
mbErr ("Missing field in META-INF/MANIFEST.MD: " ++ field) $
getManifestField manifest field
@@ -769,29 +770,29 @@ execMergeDars darFp1 darFp2 mbOutFp = do
let outFp = fromMaybe darFp1 mbOutFp
bytes1 <- B.readFile darFp1
bytes2 <- B.readFile darFp2
- let dar1 = toArchive $ BSL.fromStrict bytes1
- let dar2 = toArchive $ BSL.fromStrict bytes2
+ let dar1 = ZipArchive.toArchive $ BSL.fromStrict bytes1
+ let dar2 = ZipArchive.toArchive $ BSL.fromStrict bytes2
mf <- mergeManifests dar1 dar2
let merged =
- Archive
- (nubSortOn eRelativePath $ mf : zEntries dar1 ++ zEntries dar2)
+ ZipArchive.Archive
+ (nubSortOn ZipArchive.eRelativePath $ mf : ZipArchive.zEntries dar1 ++ ZipArchive.zEntries dar2)
-- nubSortOn keeps the first occurence
Nothing
BSL.empty
- BSL.writeFile outFp $ fromArchive merged
+ BSL.writeFile outFp $ ZipArchive.fromArchive merged
where
mergeManifests dar1 dar2 = do
let mfPath = "META-INF/MANIFEST.MF"
let dalfNames =
nubSort
[ takeFileName p
- | e <- zEntries dar1 ++ zEntries dar2
- , let p = eRelativePath e
+ | e <- ZipArchive.zEntries dar1 ++ ZipArchive.zEntries dar2
+ , let p = ZipArchive.eRelativePath e
, ".dalf" `isExtensionOf` p
]
m1 <- getEntry mfPath dar1
let m' = do
- l <- lines $ BSC.unpack $ BSL.toStrict $ fromEntry m1
+ l <- lines $ BSC.unpack $ BSL.toStrict $ ZipArchive.fromEntry m1
pure $
maybe
l
@@ -799,7 +800,7 @@ execMergeDars darFp1 darFp2 mbOutFp = do
breakAt72Chars $
"Dalfs: " <> intercalate ", " dalfNames)
(stripPrefix "Dalfs:" l)
- pure $ toEntry mfPath 0 $ BSL.fromStrict $ BSC.pack $ unlines m'
+ pure $ ZipArchive.toEntry mfPath 0 $ BSL.fromStrict $ BSC.pack $ unlines m'
execDocTest :: Options -> [FilePath] -> IO ()
execDocTest opts files = do
diff --git a/compiler/damlc/lib/DA/Cli/Visual.hs b/compiler/damlc/lib/DA/Cli/Visual.hs
index 6e51f52d2fdf..7ccec5ee4311 100644
--- a/compiler/damlc/lib/DA/Cli/Visual.hs
+++ b/compiler/damlc/lib/DA/Cli/Visual.hs
@@ -19,7 +19,7 @@ import qualified Data.NameMap as NM
import qualified Data.Set as Set
import qualified DA.Pretty as DAP
import qualified DA.Daml.LF.Proto3.Archive as Archive
-import qualified Codec.Archive.Zip as ZIPArchive
+import qualified "zip-archive" Codec.Archive.Zip as ZIPArchive
import qualified Data.ByteString.Lazy as BSL
import qualified Data.ByteString as B
import Data.Generics.Uniplate.Data
diff --git a/deps.bzl b/deps.bzl
index 53b03ed1aa19..fe6822cf6de9 100644
--- a/deps.bzl
+++ b/deps.bzl
@@ -79,6 +79,15 @@ def daml_deps():
sha256 = "6d4d6640ca3121620995ee255945161821218752b551a1a180f4215f7d124d45",
)
+ if "bzip2" not in native.existing_rules():
+ http_archive(
+ name = "bzip2",
+ build_file = "@com_github_digital_asset_daml//3rdparty/c:bzip2.BUILD",
+ strip_prefix = "bzip2-1.0.8",
+ urls = ["https://sourceware.org/pub/bzip2/bzip2-1.0.8.tar.gz"],
+ sha256 = "ab5a03176ee106d3f0fa90e381da478ddae405918153cca248e682cd0c4a2269",
+ )
+
if "io_bazel_rules_go" not in native.existing_rules():
http_archive(
name = "io_bazel_rules_go",
diff --git a/unreleased.rst b/unreleased.rst
index f6f157025e2b..81d478fff82f 100644
--- a/unreleased.rst
+++ b/unreleased.rst
@@ -14,3 +14,5 @@ HEAD — ongoing
+ [DAML Compiler] The DAML compiler was accidentally compiled without
optimizations on Windows. This has been fixed which should improve
the performance of ``damlc`` and ``daml studio`` on Windows.
++ [DAML Compiler] ``damlc build`` should no longer leak file handles so
+ ``ulimit`` workarounds should no longer be necessary.