簡體   English   中英

Python 單元測試內存消耗

[英]Python unittest memory consumption

在使用 python 的 unittest 框架時,我注意到一種行為會導致我的情況出現一些問題。 為了演示它,請查看以下代碼:

import unittest
import time

    class TC_Memory(unittest.TestCase):

        def setUp(self):
            unittest.TestCase.setUp(self)
            self.__result = False

        def test_unittest_mem1(self):
            list1 = [9876543210] * 2048*2048*9
            time.sleep(1)

            self.assertTrue(self.__result, "Failed")

        def test_unittest_mem2(self):
            list1 = [9876543210] * 2048*2048*9
            time.sleep(1)

            self.assertTrue(self.__result, "Failed")

        def test_unittest_mem3(self):
            list1 = [9876543210] * 2048*2048*9
            time.sleep(1)

            self.assertTrue(self.__result, "Failed")

        def test_unittest_mem4(self):
            list1 = [9876543210] * 2048*2048*9
            time.sleep(1)

            self.assertTrue(self.__result, "Failed")

        def test_unittest_mem5(self):
            list1 = [9876543210] * 2048*2048*9
            time.sleep(1)

            self.assertTrue(self.__result, "Failed")

        def test_unittest_mem6(self):
            list1 = [9876543210] * 2048*2048*9
            time.sleep(1)

            self.assertTrue(self.__result, "Failed")

        def test_unittest_mem7(self):
            list1 = [9876543210] * 2048*2048*9
            time.sleep(1)

            self.assertTrue(self.__result, "Failed")

        def test_unittest_mem8(self):
            list1 = [9876543210] * 2048*2048*9
            time.sleep(1)

            self.assertTrue(self.__result, "Failed")

        def test_unittest_mem9(self):
            list1 = [9876543210] * 2048*2048*9
            time.sleep(1)

            self.assertTrue(self.__result, "Failed")

    if __name__ == "__main__":
        unittest.main()

這些測試方法都做同樣的事情。 生成一個巨大的列表,等待一秒鍾,然后根據 __result 變量通過或失敗。

現在,當測試通過時,沒有什么大不了的,但是當測試失敗時,列表的內存似乎沒有被釋放。 這會導致巨大的內存消耗,因為每個測試似乎都持有其內存。 最后,在每次測試運行並打印結果后,內存被釋放,一切恢復正常。

雖然上面的代碼誇大其詞,但真實案例包含 200 多個測試,每個測試使用大約 20-30 MB 的內存。 如果這些沒有被釋放,我就會遇到內存不足的問題。

如果測試失敗,似乎 unittest 會保留測試方法變量以報告值,或者至少在這種情況下提供關於變量的報告。 我不知道,也許我在這里忽略了一些東西。

但是,我需要擺脫這種多余的內存。 到目前為止,我的選擇是:

  • 對我不再需要的任何變量調用 del。 然而,這在某種程度上破壞了垃圾收集器的好東西,並且“不必擔心內存問題”
  • 獲得更多內存。

我很想聽聽設置某種標志的可能性。 更重要的是,我很想聽到有人指出我犯的一個明顯錯誤,或者有人告訴我使用 python 或 unittest 的 xy 版本不會發生這種情況。

至於使用的版本:它是python 3.3.5 final 64bit

所以,如果還有其他問題,我很樂意回答。 如果您有任何想法,或者在黑暗中拍攝,請讓我聽到,我會嘗試一下。

提前致謝。

問題可能是測試運行器(或結果類)保留了拋出的異常,其中包含對引用大對象的幀的引用。 您可能想要做的是編寫一個不顯示此行為的自定義運行程序。 類似的東西(對不起 python2,但這是我目前所擁有的):

class CustomTestResult(TextTestResult):
      def addError(self, test, err):
           tp, vl, tb = err
           super(CustomTestResult, self).addError(test, (tp, vl, placeholder))

      def addFailure(self, test, err):
           tp, vl, tb = err
           super(CustomTestResult, self).addFailure(test, (tp, vl, placeholder))

class CustomTestRunner(TextTestRunner):
      resultclass = CustamTestResult

if __name__ == "__main__":
    import sys
    try:
        raise Exception
    except Exception as err:
        placeholder = sys.exc_info()[2]
    unittest.main(testRunner = CustomTestRunner)

不過,這里可能還有一些改進的空間。 例如,您可以遞歸地檢查回溯並確定它是否足夠大以促使它被替換(甚至可能從幀中刪除有問題的對象)。 對於被測代碼raise s 異常的情況尤其如此(在這種情況下,您可能會在回溯中受到關注,而不僅僅是占位符回溯)。

另一種解決方案可能是不在同一堆棧幀中進行分配,因為從失敗的測試創建的堆棧幀將僅包含其上的幀。 喜歡:

def mem1(self):
        list1 = [9876543210] * 2048*2048*9
        time.sleep(1)


def test_unittest_mem1(self):
        self.mem1()

        self.assertTrue(self.__result, "Failed")

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM