2016-07-31 6 views
0

C++ код:Почему модуль mmap Python работает намного медленнее, чем вызов POSIX mmap из C++?

#include <string> 
#include <fcntl.h> 
#include <sys/mman.h> 
#include <unistd.h> 
#include <sys/time.h> 

using namespace std; 
#define FILE_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) 

int main() { 
    timeval tv1, tv2, tv3, tve; 
    gettimeofday(&tv1, 0); 
    int size = 0x1000000; 
    int fd = open("data", O_RDWR | O_CREAT | O_TRUNC, FILE_MODE); 
    ftruncate(fd, size); 
    char *data = (char *) mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); 
    for(int i = 0; i < size; i++) { 
     data[i] = 'S'; 
    } 
    munmap(data, size); 
    close(fd); 
    gettimeofday(&tv2, 0); 
    timersub(&tv2, &tv1, &tve); 
    printf("Time elapsed: %ld.%06lds\n", (long int) tve.tv_sec, (long int) tve.tv_usec); 
} 

Python код:

import mmap 
import time 

t1 = time.time() 
size = 0x1000000 

f = open('data/data', 'w+') 
f.truncate(size) 
f.close() 

file = open('data/data', 'r+b') 
buffer = mmap.mmap(file.fileno(), 0) 

for i in xrange(size): 
    buffer[i] = 'S' 

buffer.close() 
file.close() 
t2 = time.time() 
print "Time elapsed: %.3fs" % (t2 - t1) 

Я думаю, что эти две программы являются по существу же, так как C++ и Python называют один и тот же системный вызов (mmap).

Но версия Python гораздо медленнее, чем C++ s:

Python: Time elapsed: 1.981s 
C++: Time elapsed: 0.062143s 

Может ли одна просьба объяснить причину, почему ММАП питон гораздо медленнее, чем C++?


Окружающая среда:

C++:

$ c++ --version 
Apple LLVM version 7.3.0 (clang-703.0.31) 
Target: x86_64-apple-darwin15.5.0 

Python:

$ python --version 
Python 2.7.11 :: Anaconda 4.0.0 (x86_64) 
+1

Что такое время выполнения для той же программы с пустым 'for i в xrange (size): x ++' loop? – deniss

ответ

6

Не mmap медленнее, но заполнение массива со значениями. Известно, что Python работает медленно, выполняя примитивные операции. Операции Использование более высокого уровня:

buffer[:] = 'S' * size 
+1

Ничего себе, он заканчивается на '0.111s'. Большое спасибо! – Sayakiss

1

Чтобы уточнить, что сказал @Daniel - любая операция, Python имеет больше накладных расходов (в некоторых случаях способ больше, как порядков), чем сопоставимый объем кода, реализующие решение в C++.

Цикл заполнения буфера действительно преступник, - но и модуль сам mmap имеет гораздо больше домашнего хозяйства, чтобы сделать, чем вы могли бы подумать, несмотря на то что он предлагает интерфейс, чья семантика, обманчиво, verrrry тесно связаны с POSIX mmap() , Вы знаете, как POSIX mmap() просто бросает вам void* (который вам нужно использовать только munmap(), чтобы очистить после него, в какой-то момент)? Python's mmap должен выделить структуру PyObject для нянчивания void* - что делает его совместимым с протоколом буфера Python, предоставляя метаданные и обратные вызовы для среды выполнения, размножения и очередей чтения и записи, поддерживая состояние GIL, очищая его распределения независимо от того, какие ошибки возникают ...

Все это требует времени и памяти. Я лично никогда не нахожу себя в модуле mmap, так как он не дает вам четкого преимущества по любой проблеме ввода-вывода, например, из-за-коробки. Вы можете так же легко использовать mmap, чтобы сделать чем медленнее, чем быстрее.

Контрастно Я часто * сделать * считают, что использование POSIXmmap()может быть очень выгодным при выполнении ввода/вывода внутри расширения Python C/C++ (при условии, что вы обращая внимания на состояние GIL), именно потому, что кодирование вокругmmap()избегает всего, что связано с внутренней инфраструктурой Python.