문제

나는 다음과 같이 시퀀스를 재귀적으로 정의하는 것을 좋아합니다.

let rec startFrom x =
    seq {
        yield x;
        yield! startFrom (x + 1)
    }

이와 같은 재귀 시퀀스를 실제로 사용해야 하는지 잘 모르겠습니다.그만큼 yield! 나타납니다 꼬리 재귀적이어야 하지만 다른 IEnumerable 내부에서 호출되기 때문에 100% 확신할 수 없습니다.내 관점에서 볼 때 코드는 각 호출을 닫지 않고 IEnumerable 인스턴스를 생성하므로 실제로 이 함수에서 메모리 누수가 발생합니다.

이 함수에서 메모리가 누출되나요?그 문제는 심지어 "꼬리 재귀"입니까?

[추가하려면 편집]:나는 답을 찾기 위해 NProf를 더듬고 있지만 SO에서 재귀 시퀀스 구현에 관한 기술적인 설명을 얻는 것이 도움이 될 것이라고 생각합니다.

도움이 되었습니까?

해결책

저는 지금 직장에 있기 때문에 Beta1보다 약간 더 새로운 비트를 보고 있습니다. 하지만 릴리스 모드의 상자에서 .Net Reflector를 사용하여 컴파일된 코드를 보면 이 두 비트가 있는 것으로 보입니다.

let rec startFromA x =    
    seq {        
        yield x     
        yield! startFromA (x + 1)    
    }

let startFromB x =    
    let z = ref x
    seq {        
        while true do
            yield !z
            incr z
    }

'릴리스' 모드에서 컴파일할 때 거의 동일한 MSIL 코드를 생성합니다.그리고 이 C# 코드와 거의 동일한 속도로 실행됩니다.

public class CSharpExample
{
    public static IEnumerable<int> StartFrom(int x)
    {
        while (true)
        {
            yield return x;
            x++;
        }
    }
}

(예:내 상자에서 세 가지 버전을 모두 실행하고 백만 번째 결과를 인쇄했는데 각 버전에는 약 1.3초, +/- 1초가 걸렸습니다.(저는 어떤 메모리 프로파일링도 ​​하지 않았습니다.제가 뭔가 중요한 것을 놓치고 있을 수도 있습니다.)

요컨대, 문제를 측정하고 보지 않으면 이런 문제에 대해 너무 많이 생각하지 않을 것입니다.

편집하다

제가 질문에 제대로 대답하지 못했다는 것을 깨달았습니다...짧은 대답은 "아니요, 누출되지 않습니다"라고 생각합니다.(캐시된 백업 저장소가 있는) 모든 '무한' IEnumerable이 '누출'된다는 특별한 의미가 있습니다('누출' 정의 방법에 따라 다름).

스택 오버플로 방지(F# 무한 시퀀스 시퀀스 사용)

IEnumerable(일명 'seq')과 LazyList에 대한 흥미로운 토론과 소비자가 특정 종류의 '누출'을 방지하기 위해 이전 결과를 '잊기' 위해 LazyList를 열심히 사용할 수 있는 방법에 대해 설명합니다.)

다른 팁

.NET 응용 프로그램은 이런 방식으로 메모리를 "누수"하지 않습니다.많은 객체를 생성하더라도 가비지 수집은 애플리케이션 자체에 대한 루트가 없는 모든 객체를 해제합니다.

.NET의 메모리 누수는 일반적으로 애플리케이션에서 사용 중인 관리되지 않는 리소스(데이터베이스 연결, 메모리 스트림 등)의 형태로 발생합니다.여러 개체를 생성한 다음 이를 버리는 이와 같은 인스턴스는 가비지 수집기가 메모리를 해제할 수 있으므로 메모리 누수로 간주되지 않습니다.

메모리 누수는 없으며 무한 시퀀스를 생성할 뿐입니다. 그러나 시퀀스는 IEnumerable이므로 메모리 문제 없이 열거할 수 있습니다.재귀가 시퀀스 생성 함수 내에서 발생한다는 사실은 재귀의 안전성에 영향을 미치지 않습니다.디버그 모드에서는 전체 디버깅을 허용하기 위해 테일 호출 최적화가 비활성화될 수 있지만 릴리스에서는 아무런 문제가 없습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top