Ce à quoi j'étais accro en traitant d'énormes fichiers dans un environnement Linux 32 bits

J'en serai peut-être à nouveau accro un jour, donc un mémorandum

J'étais accro à

Je développe toujours dans un environnement Linux 32 bits, mais j'étais accro à un certain système. Le système gère les fichiers avec un programme en langage C, Il gère une grande taille de plusieurs niveaux de Go, et quand je l'essaye, cela ne fonctionne pas du tout.

Comme le fichier est énorme, il faut du temps pour le reproduire une fois, et la cause que j'ai trouvée en déboguant tout en frustrant est très simple.

** Le fichier est trop volumineux pour être ouvert! ** **

Il semble que Linux 32 bits fait environ 2 Go. (Peut-être que mon environnement Eh bien, il y aura une limite supérieure, mais ce que vous rencontrerez réellement ... De plus, dans ce système, une application pour les programmes en langage C pour diviser les fichiers. Il ne peut même pas ouvrir le fichier. Je ne peux pas le croire ...

Solution

2018/04/23 PostScript Dans un commentaire de @ angel_p_57 J'ai entendu dire qu'il existe une option de compilation appelée ** _FILE_OFFSET_BITS **.

En suivant la page de manuel et le code OSS que j'avais, j'ai ajouté ce qui suit à CFLAGS afin que fopen puisse être fait en toute sécurité tel quel!

-D_FILE_OFFSET_BITS=64

Non, c'est merveilleux que vous puissiez changer le comportement avec une seule option, la glibc!

Extra: Ma solution, qui était indulgente à propos de la glibc

La ** commande split ** m'est venue après avoir étudié diverses méthodes de fractionnement de fichiers. Ceci est une commande pour fractionner des fichiers sous Linux, grâce à ceci Seule la commande de division a bien fonctionné.

Alors, comment devons-nous y faire face? Le mieux est de regarder le contenu du split, mais je n'ai pas le temps ** Créez un wrapper fopen en utilisant la commande split! ** **

Faire face

Ouvrez IF au lieu de fopen, si la taille est grande, divisez-le avec / usr / bin / split et enregistrez-le dans le répertoire tmp → Au moment de fread, quand je suis allé à la fin pendant fread, j'ai ouvert le fichier suivant et lu la suite.

 //fopenのラッパー
void * large_freader_open(const char *path, unsigned long maxsize) {
//....
 //サイズを見て、大きすぎたらseparate_fileでファイル分割
        unsigned long fsize = get_size(path);
        if(fsize<=maxsize) {
                //same as fopen
                handle->fp=fopen(path, "r");
                handle->max_index=1;
        } else {
                //separate file and open file as order
                separate_file(path, maxsize, handle);
                handle->fp = freader_fopen(handle);
        }
//..
 // return renvoie la structure interne au lieu de FILE *
        return handle;
//..
}

static void separate_file(const char *path, unsigned long maxsize,  struct large_freader_s *handle) {
//...
 //tmpディレクトリを取得してファイル分割
        char name[FNAME_MAX];
        get_current_dirname(handle, name, FNAME_MAX);
        snprintf(cmd, sizeof(cmd), "/usr/bin/split -d --suffix-length=6 -b %lu %s %s", maxsize, path, name);
//...
}

 //freadのラッパー
size_t large_freader_read(void * prt, size_t size,void * stream) {

//...
 //普通にfreadして
        size_t ret = fread(prt, 1, size, handle->fp);
        if(ret == size) {
                //read success, return normaly
                return ret;
        }

 //サイズ分読んでないなら次のファイルに移動
        freader_fclose(handle);
        //move to next
        handle->cur_index++;

 //全ファイル読んでるなら終わり
        if(IS_LAST_FILE(handle)) {
                //finish to read
                return ret;
        }

 //そうじゃないなら次をopenしてread
        handle->fp = freader_fopen(handle);
        if(handle->fp) {
                ret += fread(((char *)prt)+ret, 1, size-ret, handle->fp);
        }

        return ret;
}

 //内部でのfopen処理
static FILE * freader_fopen(struct large_freader_s *handle) {
 //splitしたファイル名を取得してfopen。close時にはファイル削除します。
        char dname[FNAME_MAX];
        get_current_fname(handle, dname, FNAME_MAX);
        return fopen(dname, "r");
}

Je l'ai créé chez moi pendant la nuit et l'ai publié sur github. Je voulais aussi diviser le fichier au moment de la rédaction, c'est donc une bibliothèque wrapper pour la lecture / écriture. Maintenant qu'il y a -D_FILE_OFFSET_BITS = 64, seule l'écriture peut être utilisée ...

https://github.com/developer-kikikaikai/read_write_wrapper

Mon PC domestique est 64 bits et je n'ai pas pu l'essayer fermement avec 32 bits, je vais donc résoudre les problèmes que j'ai remarqués lorsque j'ai essayé de l'utiliser dans un autre environnement.

Réflexion

2018/04/23 PostScript ・ Si quelque chose d'inattendu se produit, vérifiez d'abord les options de compilation!

Autrement, ・ Puisque fopen ne peut pas être utilisé, il est très désagréable de devoir faire popen → ls pour obtenir la taille. ・ Je crains de garantir le fonctionnement dans un environnement 32 bits ・ Il s'agit de la limite d'un système 32 bits, vous devriez donc faire de votre mieux, non? etc Vous devez compter sur une solution merdique.

Recommended Posts

Ce à quoi j'étais accro en traitant d'énormes fichiers dans un environnement Linux 32 bits
Ce à quoi j'étais accro lors de la création d'applications Web dans un environnement Windows
Ce à quoi j'étais accro avec json.dumps dans l'encodage base64 de Python
Une note à laquelle j'étais accro lors de l'émission d'un bip sous Linux
Une note à laquelle j'étais accro lors de la création d'une table avec SQL Alchemy
Quand j'ai essayé d'installer PIL et matplotlib dans un environnement virtualenv, j'en étais accro.
J'étais accro à la création d'un environnement Python venv avec VS Code
Lorsque j'ai mis Django dans mon répertoire personnel, je suis devenu accro à un fichier statique avec une erreur d'autorisation
J'étais accro au grattage avec Selenium (+ Python) en 2020
Une note à laquelle j'étais accro lors de l'exécution de Python avec Visual Studio Code
Une histoire à laquelle j'étais accro après la communication SFTP avec python
Ce à quoi j'étais accro lors de l'utilisation de Python tornado
Ce à quoi j'étais accro en combinant l'héritage de classe et l'héritage de table commune dans SQLAlchemy
Ce que j'ai fait quand j'étais en colère de le mettre avec l'option enable-shared
Ce à quoi j'étais accro lorsque l'utilisateur de traitement est passé à Python
Une histoire à laquelle j'étais accro en spécifiant nil comme argument de fonction dans Go
Ce à quoi j'étais accro en présentant ALE à Vim pour Python
Ce que j'étais accro à Python autorun
Quand j'ai essayé de gratter en utilisant des requêtes en python, j'étais accro à SSLError, donc un mémo de contournement
Une histoire à laquelle j'étais accro à essayer d'installer LightFM sur Amazon Linux
Une histoire à laquelle j'étais accro à essayer d'obtenir une URL de vidéo avec tweepy
Ce à quoi j'étais accro dans Collective Intelligence Chaprter 3. Ce n'est pas une faute de frappe, donc je pense que quelque chose ne va pas avec mon code.
J'étais accro à essayer Cython avec PyCharm, alors prenez note
[Python] Quand j'ai essayé de créer un outil de décompression avec un fichier zip que je connaissais juste, j'étais accro à sys.exit ()
Encodage de caractères lors du traitement de fichiers en Python 3
Quand j'ai essayé de créer un environnement virtuel avec Python, cela n'a pas fonctionné
Trois choses auxquelles j'étais accro lors de l'utilisation de Python et MySQL avec Docker
[Mots qui m'ont été épelés quand j'étais en première année ①] Je n'ai pas peur de créer un environnement de programmation.
Dans IPython, quand j'ai essayé de voir la valeur, c'était un générateur, donc je l'ai inventé quand j'étais frustré.
J'ai étudié les autorisations nécessaires pour supprimer les fichiers Linux.
Que faire lorsque gdal_merge génère un fichier énorme
Je veux travailler avec un robot en python.
pickle Pour lire ce qui a été fait en 2 séries avec 3 séries
Une histoire à laquelle j'étais accro chez np.where
J'étais accro à essayer logging.getLogger avec Flask 1.1.x
J'étais sobrement accro à appeler awscli à partir d'un script Python 2.7 enregistré dans crontab
Notez que j'étais accro au script npm ne passant pas dans l'environnement de vérification
J'ai essayé de créer un environnement avec WSL + Ubuntu + VS Code dans un environnement Windows
Je suis resté bloqué en essayant de spécifier un chemin relatif avec relative_to () en python
Fonctionnement pratique du clavier Linux que je veux apprendre moi-même quand j'étais à l'école
J'ai essayé de créer une classe pour rechercher des fichiers avec la méthode Glob de Python dans VBA
Éléments à prendre en compte lors de la mise en œuvre d'Airflow avec docker-compose
[IOS] Animation GIF avec Pythonista3. J'en étais accro.
Créer des pipelies Azure avec Azure DevOps dans un environnement auto-hébergé Linux
Je veux démarrer un environnement Jupyter avec une seule commande
Je souhaite utiliser un environnement virtuel avec jupyter notebook!
Mémo (mars 2020) auquel j'étais accro lors de l'installation d'Arch Linux sur MacBook Air 11'Early 2015
Qu'est-ce qui a été demandé lors de l'utilisation de Random Forest dans la pratique
Ce qui m'inquiétait lors de l'affichage d'images avec matplotlib
Ce à quoi j'étais accro lorsque j'ai construit mon propre réseau de neurones en utilisant les poids et les biais que j'ai obtenus avec le classificateur MLP de scikit-learn.
J'ai construit un environnement de l'installation de centos à l'extension de source php sur Linux, mais que faire en cas d'erreur de navigateur
Notez que j'étais accro à accéder à la base de données avec mysql.connector de Python en utilisant une application Web
Une histoire qui n'a pas fonctionné lorsque j'ai essayé de me connecter avec le module de requêtes Python
Que faire lorsque pip --user renvoie une erreur dans un environnement virtuel créé avec pyenv
Comment afficher une colonne de fichiers spécifiée sous Linux (awk)