2014-01-29 2 views
2

나는 큰 디렉토리 구조를 만들어야하는 프로젝트를 작업 해왔다. 내 첫 번째 솔루션은 존재하는 모든 dirs의 dict을 유지하는 것이었고 os.makedirs()를 사용하여 만들어지지 않은 중개자를 생성하는 경우에는 누락 된 중개자를 생성하는 것이 었습니다. 이 코드의 프로파일을 작성했을 때, 대부분의 시간 (132 초 중 105 초)이 posix.stat()을 호출하여 중개 디렉토리가 존재하지 않는다는 것을 확인하는 데 소비되었음을 알게되었습니다. 그러나 나는 빈 디렉토리에이 전체 구조를 만들었으므로 중간 디렉토리가 존재하지 않는다는 것을 이미 알고 있었다.명시 적으로 호출 할 때 os.mkdir()이 느린 이유는 무엇입니까?

class DirTree: 
    def __init__(self, root): 
    self.root = os.path.abspath(root) 
    self.tree = {} 
    def makedirs(self, path): 
    relpath = os.path.relpath(path, self.root).replace('\\', '/') 
    built = self.root 
    node = self.tree 
    for directory in relpath.split('/'): 
     built = os.path.join(built, directory) 
     if directory in node: 
      node = node[directory] 
     else: 
      node[directory] = {} 
      node = node[directory] 
      os.mkdir(built, 0777) 

:

이를 활용하기 위해 나는 계속하고 OS를 쿼리하지 않고 생성 된의 디렉토리를 결정할 수 있도록 내부 메모 디렉토리 트리의 구조를 설명하는 코드의 버전을 썼다 이 코드는 더 빨리 실행되지만 프로파일 러를 통해 실행할 때 os.mkdir()에 대한 동일한 4068 호출이 이제 4 배 더 길어집니다 (24 초 대신 94 초). os.makedirs()가 호출 할 때보 다이 함수가 내 함수라고 할 때 왜이 함수가 더 오랜 시간이 걸리는지 이해하지 못합니다. 아무도 이유가 무엇입니까?

답변

1

디렉토리를 만들기 전에 os.mkdirs가 경로 구성 요소의 존재를 확인하는 것이 옳습니다. see here, line 136. 여러분의 코드와 os.mkdir은 linux가 mkdir이라는 시스템 호출을 해석하는 mkdir의 실제 구현을 위해 cc-python 모듈 posixmodule.c을 사용합니다.

"a"가 존재하지 않는다면 확실히 "a/b"도 존재하지 않기 때문에 os.mkdir는 stat가 너무 오래 걸리면 불필요하게 시간이 많이 소요됩니다.

strace을 사용하면 두 구현 모두 mkdir을 동일한 횟수만큼 호출하지만 경로가 상대 경로 인 경우 생성 한 함수는 상대 경로를 사용하는 os.mkdirs와 비교하여 절대 경로를 구성합니다.

가능한 추가 시간은 "."에 매회 추가하는 대신 올바른 디렉토리를 찾기 위해 디렉토리 구조를 검색하는 OS입니다.

os.mkdirs

stat("a/b/c", 0x7fff34b1c4d0)   = -1 ENOENT (No such file or directory) 
stat("a/b", 0x7fff34b1c260)    = -1 ENOENT (No such file or directory) 
stat("a", 0x7fff34b1bff0)    = -1 ENOENT (No such file or directory) 
mkdir("a", 0777)      = 0 
mkdir("a/b", 0777)      = 0 
mkdir("a/b/c", 0777)     = 0 
mkdir("a/b/c/d", 0777)     = 0 

수정 mkdirs

말했다되고 그건
mkdir("/tmp/a", 0777)     = 0 
mkdir("/tmp/a/b", 0777)     = 0 
mkdir("/tmp/a/b/c", 0777)    = 0 
mkdir("/tmp/a/b/c/d", 0777)    = 0 

, 나는 결과를 재현 할 수 있습니다. 나는 시간이 (cprofile 명령을 사용하여) 소비에서 mkdir

4003 0.132 0.000 0.132 0.000 {posix.mkdir} 

수정 mkdirs

4003 0.147 0.000 0.147 0.000 {posix.mkdir} 

같은

os.mkdirs에 관한 os.mkdirs 또는 소스에 의해 호출하지만이 있었다는 것을 발견 posixpath의 새로운 소스에서 많은 시간을 보냈다

4000 0.104 0.000 1.003 0.000 posixpath.py:400(relpath) 

아마도 이것은 ar 방법의 프로필 또는 미묘한 설치 방법.

+0

나는 그것이 C면에 있다고 생각하지 않습니다. 'stat()'호출을하는'makedirs()'에서'head와 tail이 아니라 path.exists (head) :'가 아닌 것으로 보인다. – glglgl

관련 문제