2017-02-20 7 views
9

Я работаю над проектом компилятора исследования, предназначенным для работы в качестве службы. Одним из требований является то, что некоторые пользователи могут иметь ограниченное использование памяти (например, «вызовы от IP a.b.c.d могут использовать до 30 мб кучной памяти») при обработке вызовов.Можно ли ограничить использование памяти в каждой функции/монаде/потоке в Haskell?

Реализация моего прототипа, написанная на C, просто использует пул памяти, равный malloc 'непосредственно (на самом деле довольно сложно получить право из-за эффективных типов). Ручное управление памятью.

Есть ли способ достичь этого в Haskell, ограничив использование кучи на функции, монаде или легкой нити? (Я принимаю предложение других функциональных языков, которые могли бы позволить мне сделать это.)

+0

Что именно вы пытаетесь ограничить? Ограничение произвольной памяти для произвольного кода Haskell, вероятно, невозможно, но вы можете ограничить доступ к определенному ресурсу, скрывая его за классом типа. – Cirdec

+7

Процессы операционной системы могут иметь ограниченную память. Одним из возможных решений является разветвление нового процесса и ['setResourceLimit'] (https://hackage.haskell.org/package/unix-2.7.2.1/docs/System-Posix-Resource.html) для нового процесса и общайтесь с ним чем-то вроде [Remote] (https://hackage.haskell.org/package/remote-0.1.1/docs/Remote.html). Вам нужно будет ограничить выполнение кода в новом процессе чем-то менее мощным, чем 'IO()'. – Cirdec

+0

Да, я пытаюсь ограничить использование общей памяти для этого процесса компиляции. Это может быть очень дорого, я был бы уязвим к DoS, если бы я не ограничил использование кучи. – paulotorrens

ответ

10

В последних версиях GHC, можно установить счетчики и пределы распределения для каждого потока, используя setAllocationCounter и enableAllocationLimit от GHC.Conc. Когда предел установлен и счетчик достигает 0, поток получает асинхронное исключение.

Счетчики измеряют распределение, а не размер живого набора. Например, этот код достигнет предела, несмотря на живой набор никогда не становится очень большой:

{-# LANGUAGE NumDecimals #-} 
module Main where 

import Data.Foldable (for_) 
import System.IO 
import GHC.Conc (setAllocationCounter,enableAllocationLimit) 

main :: IO() 
main = 
    do setAllocationCounter 2e9 
    enableAllocationLimit 
    let writeToHandle h = 
      for_ ([1..]::[Integer]) 
       (hPutStrLn h . show) 
    withFile "/dev/null" WriteMode writeToHandle 
    return() 

Allocation немного сырой в качестве меры, но он все еще может быть полезным для выявления некоторых «из-под контроля» вычислений.

This blog post автор: Simon Marlow подробнее.

+0

достаточно близко. Благодарю. – paulotorrens

Смежные вопросы