相关疑难解决方法(0)

如何找出GHC的数据类型的内存表示?

最近,诸如计算Hashmap的大小之类的博客条目解释了如何推断常用容器类型的空间复杂性.现在我面临的问题是如何实际"看到"我的GHC版本选择的内存布局(取决于编译标志和目标体系结构),用于奇怪的数据类型(构造函数),例如

data BitVec257 = BitVec257 {-# UNPACK #-} !Word64
                           {-# UNPACK #-} !Word64
                           {-# UNPACK #-} !Bool
                           {-# UNPACK #-} !Word64
                           {-# UNPACK #-} !Word64

data BitVec514 = BitVec514 {-# UNPACK #-} !BitVec257
                           {-# UNPACK #-} !BitVec257
Run Code Online (Sandbox Code Playgroud)

在C中有sizeofoffsetof运算符,它允许我"看到"为C字段选择的大小和对齐方式struct.

我试着看看GHC Core希望在那里找到一些提示,但我不知道该找什么.有人能指出我正确的方向吗?

haskell ghc

15
推荐指数
2
解决办法
1604
查看次数

如何确定Haskell中类型的大小?

假设我创建了一个类型如下:

data RequestAck = 
         RequestAck { ackOK :: Word32, ackMsgCode :: Word32 } 
Run Code Online (Sandbox Code Playgroud)

我可以看到它是2*4字节大,并使其在某处保持不变.

唯一的问题是,一旦我在类型中添加了一个字段,我就必须记得更新我的常量.

是否有一个功能可以为我提供给定类型的大小,例如t -> Int

接近我想要的功能是

gsize :: Data a => a -> Int

在Data.Generics.Schemes模块中,但我不想让我的类型成为一个实例Data.

那里有更通用的解决方案吗?

可以肯定的是,我正在寻找一个对静态类型进行操作的函数,例如,我不想传递实例,而是传递类型本身.

byte haskell types

14
推荐指数
1
解决办法
2060
查看次数

值构造函数和元组之间有什么区别?

据说 Haskell元组只是代数数据类型的不同语法.类似地,有一些示例说明如何使用元组重新定义值构造函数.

例如,Haskell中的Tree数据类型可能被写为

data Tree a = EmptyTree | Node a (Tree a) (Tree a)
Run Code Online (Sandbox Code Playgroud)

可以像这样转换为"元组形式":

data Tree a = EmptyTree | Node (a, Tree a, Tree a)
Run Code Online (Sandbox Code Playgroud)

Node第一个示例中的值构造函数tuple与第二个示例中的值构造函数有什么区别?ie Node a (Tree a) (Tree a)vs. (a, Tree a, Tree a)(除了语法之外)?

在引擎盖下,Node a (Tree a) (Tree a)每个位置的3元组适当类型只是一种不同的语法?

我知道你可以部分应用一个值构造函数,例如Node 5它将具有类型:(Node 5) :: Num a => Tree a -> Tree a -> Tree a

您也可以使用(,,)函数来部分应用元组...但是这不知道未绑定条目的潜在类型,例如:

Prelude> :t (,,) 5
(,,) 5 …
Run Code Online (Sandbox Code Playgroud)

haskell tuples algebraic-data-types value-constructor

12
推荐指数
2
解决办法
785
查看次数

Haskell可以评估而不是垃圾收集列表中的随机索引吗?

据我所知,Haskell只有当某些东西超出范围时才会收集垃圾,因此顶级绑定只会被评估一次并且永远不会超出范围.因此,如果我在GHCI中运行此代码,将评估并保存前50个元素.

let xs = map f [0..]
take 50 xs
Run Code Online (Sandbox Code Playgroud)

我的问题是当我执行以下代码段时会发生什么:xs !! 99.垃圾收集器保存了什么?可以

  1. 保留索引0 - 49的结果,索引50 - 98的thunk,索引99的结果,索引100+的thunk
  2. 保留索引0 - 49的结果,索引50+的thunk
  3. 保留索引0 - 99的结果,索引100+的thunk

garbage-collection haskell lazy-evaluation

11
推荐指数
2
解决办法
423
查看次数

reallyUnsafePtrEquality#在没有字段的构造函数上

我的理解是,没有字段的类型的构造函数是"静态分配"的,GHC 在所有用途之间共享这些构造函数,并且GC不会移动它们.

如果这是正确的,那么我希望使用reallyUnsafePtrEquality#on值FalseNothing非常安全(没有错误否定或肯定),因为它们只能表示为与该构造函数的单个实例相同的指针.

我的推理是否正确?是否有任何潜在的问题或理由怀疑在不久的将来版本的GHC中这可能会变得不安全?

haskell ghc

9
推荐指数
1
解决办法
477
查看次数

盒装和非盒装整数的内存布局?

我的理解是Int值是指向thunk(双重间接)的指针,而未装箱的Int#只是指向32/64位int的指针.那是对的吗?指针如何编码它指的是未装箱的值?

所述的Haskell标准规定,一个Int是"A固定精度整数类型至少与所述范围[-2 ^ 29 .. 2 ^ 29-1]".在GHC中是否有一些优化,其中那些额外的位用于消除间接?

haskell ghc

8
推荐指数
1
解决办法
644
查看次数

存在量化类型的内存占用和相关的优化技术

考虑使用存在主义的以下数据模型:

data Node a = Node a (Map TypeRep AnyNode)
data AnyNode = forall a. Show a => AnyNode a
Run Code Online (Sandbox Code Playgroud)

先前已经解释了关于标准类型的存储器占用的规则.现在,存在类型的规则是什么,比如AnyNode

是否有任何优化技术,例如一些使用unsafeCoerce可以避开存在性声明的变通方法?我问这个是因为类似的类型Node将被放置在高内存密集型lib的成本中心,所以内存占用就足够了,这就是为什么最脏的黑客是受欢迎的.

memory optimization haskell

8
推荐指数
1
解决办法
163
查看次数

haskell中构造函数的内存使用情况

可能重复:
Haskell数据类型的内存占用量

在解决组合问题时,我经常将解决方案表示为一个字符串,例如.1010100010110111000110 ...你明白了.

我认为当我使用[Int]比特串时,Int总是花费相同数量的内存,无论实际数量有多大(因为Int它是有界的,相反Integer),因为计算机只记得比特表示,而且String会据我所知,占据更多空间.

我的想法是使用数据类型

data Bits = Empty | Zero Bits | One Bits deriving (Eq,Ord,Show)
Run Code Online (Sandbox Code Playgroud)

但多少内存的构造Empty,ZeroOne用比较Int的?

memory haskell

7
推荐指数
1
解决办法
371
查看次数

Haskell和可变结构的性能

我正在研究优化Haskell代码中给出的答案,并注意到与Python相比,使用小输入确实会导致更快的Haskell运行.

但随着数据集规模的扩大,Python占据了主导地位.使用基于散列映射的版本已经改善了性能,但它仍然落后.

更糟糕的是,我尝试将Python的词典音译为哈希表并观察到性能受到严重打击.我真的想了解发生了什么,因为我需要可变结构用于未来的应用程序.

这是稍微修改过的Python代码:

#! /usr/bin/env python2.7
import random
import re
import cPickle

class Markov:
    def __init__(self, filenames):
        self.filenames = filenames
        self.cache = self.train(self.readfiles())
        picklefd = open("dump", "w")
        cPickle.dump(self.cache, picklefd)
    print "Built a db of length "+str(len(self.cache))
        picklefd.close()

    def train(self, text):
        splitted = text.split(' ')
        print "Total of %d splitted words" % (len(splitted))
        cache = {}
        for i in xrange(len(splitted)-2):
            pair = (splitted[i], splitted[i+1])
            followup = splitted[i+2]
            if pair in cache:
                if followup not in cache[pair]:
                    cache[pair][followup] = …
Run Code Online (Sandbox Code Playgroud)

performance haskell hashtable mutable

7
推荐指数
1
解决办法
905
查看次数

严格的单构造函数单字段数据声明与newtype

Haskell中的`data`和`newtype`之间的区别以及其他一些问题解决了数据和newtype之间的一般差异.我的问题非常具体.如果G是某种类型,是否有任何区别

data T = T !G

newtype T = T G

它们似乎具有相同的严格属性,我不明白为什么编译器有任何理由以不同的方式编译它们,但也许我错过了一些东西.

haskell

6
推荐指数
1
解决办法
426
查看次数

简单的多线程Haskell的大量内存消耗

我有一个相对简单的"复制"程序,它只是将一个文件的所有行复制到另一个文件.我玩弄Haskell的并发支持TMQueueSTM所以我想我会尝试这样的:

{-# LANGUAGE BangPatterns #-}

module Main where

import Control.Applicative
import Control.Concurrent.Async              -- from async
import Control.Concurrent.Chan
import Control.Concurrent.STM (atomically)
import Control.Concurrent.STM.TMQueue        -- from stm-chans
import Control.Monad (replicateM, forM_, forever, unless)
import qualified Data.ByteString.Char8 as B
import Data.Function (fix)
import Data.Maybe (catMaybes, maybe)
import System.IO (withFile, IOMode(..), hPutStrLn, hGetLine)
import System.IO.Error (catchIOError)

input  = "data.dat"
output = "out.dat"
batch = 100 :: Int

consumer :: TMQueue B.ByteString -> IO ()
consumer q = withFile output WriteMode …
Run Code Online (Sandbox Code Playgroud)

queue multithreading haskell ghc

6
推荐指数
1
解决办法
384
查看次数

什么是表示红黑树的最有效方法?

冈崎使用(基本上)

data Color = R | B
data RB a = L | T {-# UNPACK #-}!Color !(RB a) !a !(RB a)
Run Code Online (Sandbox Code Playgroud)

我知道在C中,颜色通常以更加繁琐的方式处理以节省空间,做一些事情,比如使指针的低位代表颜色(我想通常指向节点的指针编码它的颜色,但它也会可以通过使左或右指针来模拟Okasaki的结构一个节点代表它颜色).

显然,在Haskell中这种小小的变化是不可能的.那么,如何在Haskell中最有效地表示节点?

data RB' a = L | B !(RB a) !a !(RB a) | R !(RB a) !a !(RB a)
Run Code Online (Sandbox Code Playgroud)

似乎可能是合理的内存效率,但它似乎也可能使模式匹配相当冗长.

haskell

5
推荐指数
1
解决办法
369
查看次数

优化一个多次调用的简单解析器

我用自定义文件编写了一个解析器attoparsec.分析报告表明,大约67%的内存分配是在一个名为的函数中完成的tab,这也耗费了大部分时间.该tab功能是非常简单的:

tab :: Parser Char
tab = char '\t'
Run Code Online (Sandbox Code Playgroud)

整个分析报告如下:

       ASnapshotParser +RTS -p -h -RTS

    total time  =       37.88 secs   (37882 ticks @ 1000 us, 1 processor)
    total alloc = 54,255,105,384 bytes  (excludes profiling overheads)

COST CENTRE    MODULE                %time %alloc

tab            Main                   83.1   67.7
main           Main                    6.4    4.2
readTextDevice Data.Text.IO.Internal   5.5   24.0
snapshotParser Main                    4.7    4.0


                                                             individual     inherited
COST CENTRE        MODULE                  no.     entries  %time %alloc   %time %alloc

MAIN               MAIN                     75           0    0.0    0.0   100.0 …
Run Code Online (Sandbox Code Playgroud)

performance haskell attoparsec

5
推荐指数
1
解决办法
185
查看次数