Soucis de fuite mémoire

Bonjour,

j’ai un petit soucis que je n’arrive pas à résoudre.
j’ai une fuite mémoire que je n’arrive pas à résorber sur le code ci-dessous.
Ce code est inspiré de la documentation apple développer.
J’ai souhaité effectuer le traitement d’une multitudes de données json (d’où la boucle for ) (environ un million de fichiers json)
Ce qui me chagrine, c’est que la mémoire utilisée augmente au fur et à mesure que la boucle for s’exécute
, et je n’arrive pas à trouver de solution pour vider la mémoire persistante qui semble être crée via decoder.decode.
Est-ce que quelqu’un pourrait m’aiguiller sur la démarche à suivre pour supprimer cette mémoire persistante? (je n’ai pas trouvé de fonction permettant de supprimer une variable ou constante sous swift, à priori tout est géré par l’Automatic Reference Counting, mais c’est une notion obscure que je ne maitrise pas.
je vous remercie par avance.

Fabrice

struct GroceryProduct: Codable {
    var name: String
    var points: Int
    var description: String?
}
func myJson()->Data{
    let json = """
    {
        "name": "Durian",
        "points": 600,
        "description": "A fruit with a distinctive scent."
    }
    """.data(using: .utf8)!
    return json
}



for _ in 1...1000000 {
    let decoder = JSONDecoder()
    let json = """
    {
        "name": "Durian",
        "points": 600,
        "description": "A fruit with a distinctive scent."
    }
    """.data(using: .utf8)!
    var product = try decoder.decode(GroceryProduct.self, from: json)
    //print(product.name) // Prints "Durian"
    
}

Là comme ça, sans trop réfléchir je te dirais d’essayer de sortir la création de JSONDecoder() de la boucle. A priori tu as besoin d’un seul décodeur !

Bonsoir Draken,

Merci pour ce conseil.
j’ai donc sorti le

let decoder = JSONDecoder()
var product = GroceryProduct()

de la boucle for.
le script prend toujours autant de mémoire .
Dans l’exemple de code, il prend 190Mo…
il semblerait que j’ai une fuite mémoire sur la ligne :

     product = try decoder.decode(GroceryProduct.self, from: json)

Je n’arrive pas à trouver le moyen d’enlever cette mémoire persistante.

Est ce que tu penses savoir d’ou vient le soucis? je n’arrive pas à trouver d’informations sur d’éventuels problèmes avec decoder.decode() sur différents forums

Cordialement,

Fabrice

Pas la moindre idée. Mais franchement faire un traitement séquentiel sur un million d’enregistrement c’est énorme … Pas étonnant que cela accumule des données en mémoire.

Moi j’essayerais de faire un traitement asynchrone, pour dispatcher la tâche en petits processus, traitables indépendament par les différents Cores, en fonction des disponibilités du Device. Cela évite de bloquer la machine le temps du traitement, forcément long avec un million d’opérations. Et devrais permettre à iOS de libérer la mémoire tampon au fur et à mesure de la progression.

Comment faire ? Je ne sais pas, cela a beaucoup évolué ces dernières années, et je n’ai pas vraiment codé depuis longtemps. Tu devrais jeter un oeil sur les nouvelles fonctions de gestion des processus asynchrones d’iOS 15. Il parait que c’est très simple à utiliser et très performant (mais limite ton développement à iOS 15 au minimum).

Bonjour Draken,

J’ai enfin trouvé une solution à mon problème.
Je l’expose dans le cas ou cela arrive à d’autres personnes.
Après une recherche dans les entrailles historiques d’IOS, j’ai fait connaissance de @autoreleasepool et directement hérité d’objective-C à priori.

Si j’ai bien compris son utilisation l’utilisation, au lieu de laisser ARC libérer les objets automatiquement, nous pouvons lui indiquer à certains endroit de libérer les données à un moment précis en utilisant la fonction autoreleasepool{}
du coup la partie modifiée de mon code de démonstration devient :

let decoder = JSONDecoder()
var product = GroceryProduct()
for _ in 1...1000000 {
    autoreleasepool{
    let json = """
    {
        "name": "Durian",
        "points": 600,
        "description": "A fruit with a distinctive scent."
    }
    """.data(using: .utf8)!
    product = try! decoder.decode(GroceryProduct.self, from: json)
    //let products =  try? GroceryProduct(name: "durian", points: 100, description: "bonjour")
    //print(product.name) // Prints "Durian"
    //product = nil
    print(type(of: product))
    }
}

Du coup, au lieu de prendre 190MO, le code de démonstration ne prend plus que 5.9Mo.

Il est clair que je devrais utiliser un système de traitement multi-core afin d’avoir un temps de calculs optimisés, et éviter d’avoir un code trop énergivore. mais pour l’instant, je ne maitrise pas ce concept (si tu as quelques tutos à me montrer, de préférence en français :-D, je suis preneur )

Dans tous les cas, Merci Draken, car sans ta réflexion, cela m’a permis de cibler mes recherches et de voir ma problématique sous un autre angle.

Fabrice

A partir de maintenant, je ne t’aiderais plus … Quelqu’un aimant le Durian, la pire abomination de l’univers mérite une place en Enfer, au mieux !

Edit : le dernier cours de Maxime sur le Swift

traite de l’utilisation des fonctions asynchrones en Swift 5.5. - chapitre 6.1 et 6.2 - je n’ai pas encore visionné ces vidéos. Désolé Maxime :sweat_smile:, mais il y avait la saison 3 des Titans sur Netflix, alors … !

Et au pire ? J’aime beaucoup le Durian, certes, interdit à certaines époques dans les aéroports extrême-orientaux en raison de son dodeur pénétrante et particulière. Je m’en suis fait, jadis, livrer un par transporteur, depuis chez les frères Tang, dans le XIIIe à Paris.
Le livreur a vu ce paquet de la taille d’une tête emballée, perçu le parfum malgré plusieurs épaisseurs de plastique et de carton, et a exigé que l’on déballât devant lui l’objet, la voix mal assurée et les jambes flageolantes, persuadé de faire son devoir au risque de sa vie. La découverte de ce merveilleux fruit, qui ressemble au fruit du Jacquier en plus gros, l’a détendu immédiatement ; il a repris son souffle, retrouvé son sourire, persuadé qu’il était d’avoir livré une tête à un parrain.
Le goût était suave.
On ne peut guère le décrire : associant des saveurs sucrées, aromatiques et fromagères, une consistance lisse et presque grasse, une chair blanche à l’architecture difficile à décrire, le durian est sans aucun doute le plus exotique des fruits que l’on peut se procurer en France. Le Durian ne se décode donc pas.

C’est carrément immonde ce fruit, enfin pour les Occidentaux !

Il y a une bizarrerie génétique là-dedans. Pour la plupart des Occidentaux l’odeur et le goût de ce fruit sont une véritable abomination, alors que les Asiatiques trouvent ça agréable. Quand j’ai appris ça, j’ai fait le brave et hop … rapide aller retour à Tang pour en acheter. Mon dieu, quelle horreur !

Il y a quelques années un ami a acheté des gâteaux de Lune au Durian, pour une fête, sans savoir ce que c’était. Le choc au moment du dessert. On a tous faillit le lapider après avoir essayé. Le seul à apprécier a été un malgache, dont les ancêtres asiatiques l’ont préservés de l’horreur gustative.

La prochaine fois, je choisirai une pomme pour éviter l’enfer et tenter une rentrée au paradis :wink:
Merci pour le lien, je reprendrai un abonnement courant janvier, les achats de noël sont déjà passés par là :slight_smile:

Je conseille à chacun d’essayer pour savoir ce qu’il en pense, mais je ne suis pas sûr que ce puisse remplacer un bon vieux test ADN pour savoir si on a des ancêtres asiates, c’est plus culturel qu’autre chose, ces trucs-là.
Étant donné les aspérités solides et aiguisées dont est hérissée la surface du fruit, je recommande de ne pas s’en servir aux fins de lapidation en tous cas…

Mais je n’ai jamais vu cette série moi, il va falloir que je teste :thinking: Tu seras pardonné si j’apprécie la série. Sinon on pourra trouver une sanction qui implique ce fruit que tu affectionnes tant.