标签: ghc

减少Haskell程序中的垃圾收集暂停时间

我们正在开发一个程序,它接收和转发"消息",同时保留这些消息的临时历史记录,以便它可以告诉您消息历史记录(如果请求).消息以数字方式标识,通常大小约为1千字节,我们需要保留数十万条这些消息.

我们希望优化此程序的延迟:发送和接收消息之间的时间必须低于10毫秒.

该程序是用Haskell编写的,并用GHC编译.但是,我们发现垃圾收集暂停对于我们的延迟要求来说太长了:在我们的实际程序中超过100毫秒.

以下程序是我们的应用程序的简化版本.它使用a Data.Map.Strict来存储消息.消息ByteString由a标识Int.以递增的数字顺序插入1,000,000条消息,并且不断删除最旧的消息以使历史记录最多保留200,000条消息.

module Main (main) where

import qualified Control.Exception as Exception
import qualified Control.Monad as Monad
import qualified Data.ByteString as ByteString
import qualified Data.Map.Strict as Map

data Msg = Msg !Int !ByteString.ByteString

type Chan = Map.Map Int ByteString.ByteString

message :: Int -> Msg
message n = Msg n (ByteString.replicate 1024 (fromIntegral n))

pushMsg :: Chan -> Msg -> IO Chan
pushMsg chan (Msg msgId msgContent) =
  Exception.evaluate $
    let
      inserted = Map.insert …
Run Code Online (Sandbox Code Playgroud)

performance garbage-collection haskell latency ghc

125
推荐指数
4
解决办法
6600
查看次数

小型Haskell程序用GHC编译成巨大的二进制文件

即使是简单的小型Haskell程序也会变成巨大的可执行文件.

我已经编写了一个小程序,它被编译(用GHC)到二进制文件,大小扩展到7 MB!

甚至可以将一个小的Haskell程序编译成巨大的二进制文件?

如果有的话,我可以做些什么来减少这个?

linker haskell ghc glfw static-linking

123
推荐指数
2
解决办法
1万
查看次数

Haskell数据类型的内存占用量

如何找到在Haskell中存储某些数据类型值所需的实际内存量(主要是使用GHC)?是否可以在运行时(例如在GHCi中)对其进行评估,还是可以从其组件中估算复合数据类型的内存要求?

在一般情况下,如果类型的存储需求ab已知的,什么是代数数据类型,如内存开销:

data Uno = Uno a
data Due = Due a b
Run Code Online (Sandbox Code Playgroud)

例如,这些值占用的内存中有多少字节?

1 :: Int8
1 :: Integer
2^100 :: Integer
\x -> x + 1
(1 :: Int8, 2 :: Int8)
[1] :: [Int8]
Just (1 :: Int8)
Nothing
Run Code Online (Sandbox Code Playgroud)

据我所知,由于垃圾收集延迟,实际的内存分配更高.由于惰性评估,它可能会有很大的不同(并且thunk大小与值的大小无关).问题是,给定数据类型,在完全评估时它的值会占用多少内存?

我发现:set +sGHCi中有一个选项可以查看内存统计信息,但目前尚不清楚如何估算单个值的内存占用量.

haskell memory-management ghc algebraic-data-types

120
推荐指数
2
解决办法
6992
查看次数

为什么Haskell的"无所事事"功能,id,消耗大量内存?

Haskell有一个标识函数,它返回输入不变.定义很简单:

id :: a -> a
id x = x
Run Code Online (Sandbox Code Playgroud)

所以为了好玩,这应该输出8:

f = id id id id id id id id id id id id id id id id id id id id id id id id id id id
main = print $ f 8
Run Code Online (Sandbox Code Playgroud)

几秒钟后(根据任务管理器大约2 GB的内存),编译失败了ghc: out of memory.同样,翻译说ghci: out of memory.

由于它id是一个非常简单的函数,我不希望它在运行时或编译时成为内存负担.什么是用于的内存?

haskell ghc

112
推荐指数
1
解决办法
6426
查看次数

在GHC Haskell中何时自动记忆?

我无法弄清楚为什么m1显然被记忆,而m2不在下面:

m1      = ((filter odd [1..]) !!)

m2 n    = ((filter odd [1..]) !! n)
Run Code Online (Sandbox Code Playgroud)

m1 10000000在第一次调用时大约需要1.5秒,而后续调用需要一小部分(大概是缓存列表),而m2 10000000总是花费相同的时间(每次调用重建列表).知道发生了什么事吗?关于GHC是否以及何时会记忆功能,是否有任何经验法则?谢谢.

haskell memoization ghc

106
推荐指数
3
解决办法
9781
查看次数

有没有办法让GHC提供类型孔的类型类约束?

目前的行为

Prelude> show _

<interactive>:7:6:
    Found hole ‘_’ with type: a0
    Where: ‘a0’ is an ambiguous type variable
    Relevant bindings include it :: String (bound at <interactive>:7:1)
    In the first argument of ‘show’, namely ‘_’
    In the expression: show _
    In an equation for ‘it’: it = show _
Run Code Online (Sandbox Code Playgroud)

期望的行为

如果GHC还告诉我输入的孔具有Show类型类约束,那将是很好的.

杂项

GHC版本7.8.1

haskell types ghc

102
推荐指数
1
解决办法
1867
查看次数

为什么这个Haskell代码用-O运行得慢?

这段Haskell代码运行慢得多-O,但-O应该是非危险的.谁能告诉我发生了什么?如果重要,它是尝试解决这个问题,它使用二进制搜索和持久段树:

import Control.Monad
import Data.Array

data Node =
      Leaf   Int           -- value
    | Branch Int Node Node -- sum, left child, right child
type NodeArray = Array Int Node

-- create an empty node with range [l, r)
create :: Int -> Int -> Node
create l r
    | l + 1 == r = Leaf 0
    | otherwise  = Branch 0 (create l m) (create m r)
    where m …
Run Code Online (Sandbox Code Playgroud)

optimization haskell ghc compiler-bug

86
推荐指数
1
解决办法
2841
查看次数

为什么我不能使String成为类型类的实例?

鉴于:

data Foo =
  FooString String
  …

class Fooable a where --(is this a good way to name this?)
  toFoo :: a -> Foo
Run Code Online (Sandbox Code Playgroud)

我想做String一个实例Fooable:

instance Fooable String where
  toFoo = FooString
Run Code Online (Sandbox Code Playgroud)

然后GHC抱怨:

Illegal instance declaration for `Fooable String'
    (All instance types must be of the form (T t1 ... tn)
     where T is not a synonym.
     Use -XTypeSynonymInstances if you want to disable this.)
In the instance declaration for `Fooable String'
Run Code Online (Sandbox Code Playgroud)

如果相反我使用[Char]: …

haskell type-systems typeclass ghc

84
推荐指数
3
解决办法
7489
查看次数

如何阅读GHC核心"证据"?

我写了一小部分Haskell来弄清楚GHC如何证明对于自然数,你只能将偶数的一半:

{-# LANGUAGE DataKinds, GADTs, KindSignatures, TypeFamilies #-}
module Nat where

data Nat = Z | S Nat

data Parity = Even | Odd

type family Flip (x :: Parity) :: Parity where
  Flip Even = Odd
  Flip Odd  = Even

data ParNat :: Parity -> * where
  PZ :: ParNat Even
  PS :: (x ~ Flip y, y ~ Flip x) => ParNat x -> ParNat (Flip x)

halve :: ParNat Even -> Nat
halve PZ     = Z
halve …
Run Code Online (Sandbox Code Playgroud)

haskell formal-verification proof ghc haskell-platform

84
推荐指数
1
解决办法
1242
查看次数

Haskell中的孤立实例

使用该-Wall选项编译我的Haskell应用程序时,GHC会抱怨孤立的实例,例如:

Publisher.hs:45:9:
    Warning: orphan instance: instance ToSElem Result
Run Code Online (Sandbox Code Playgroud)

类型类ToSElem不是我的,它由HStringTemplate定义.

现在我知道如何解决这个问题(将实例声明移动到声明Result的模块中),我知道为什么GHC更愿意避免孤立的实例,但我仍然相信我的方式更好.我不在乎编译器是否带来不便 - 而不是我.

我想ToSElem在Publisher模块中声明我的实例的原因是因为它是依赖于HStringTemplate的Publisher模块,而不是其他模块.我试图保持关注点的分离,并避免让每个模块依赖于HStringTemplate.

我认为,与Java的接口相比,Haskell类型类的优点之一是它们是开放的而不是封闭的,因此实例不必在与数据类型相同的位置声明.GHC的建议似乎是忽略了这一点.

所以,我正在寻找的是要么认可我的想法是正确的,要么我有理由忽视/压制这个警告,或者更有说服力的反对我做事的做法.

haskell typeclass ghc

82
推荐指数
5
解决办法
7764
查看次数