2012-03-30 7 views
3

Ich arbeite an einer Upload-App, die Dateien vor dem Hochladen aufteilt. Es teilt die Dateien auf, um zu verhindern, dass sie von iOS geschlossen werden, um zu viel Speicher zu verwenden, da einige der Dateien ziemlich groß sein können. Es wäre toll, wenn ich könnte, anstatt die maximale "Chunk" -Größe zu setzen, die maximale Speicherbelegung einstellen und die Größe damit bestimmen.Erhalte Speicherplatz, der von der App in iOS verwendet wird

So etwas wie dieses

#define MAX_MEM_USAGE 20000000 //20MB 
#define MIN_CHUNK_SIZE 5000 //5KB 

-(void)uploadAsset:(ALAsset*)asset 
{ 
    long totalBytesRead = 0; 
    ALAssetRepresentation *representation = [asset defaultRepresentation]; 
    while(totalBytesRead < [representation size]) 
    { 
     long chunkSize = MAX_MEM_USAGE - [self getCurrentMemUsage]; 
     chunkSize = min([representation size] - totalBytesRead,max(chunkSize,MIN_CHUNK_SIZE));//if I can't get 5KB without getting killed then I'm going to get killed 
     uint8_t *buffer = malloc(chunkSize); 
     //read file chunk in here, adding the result to totalBytesRead 
     //upload chunk here 
    } 
} 

ist im Wesentlichen, was ich werde. Ich kann anscheinend keine Möglichkeit finden, die aktuelle Speichernutzung meiner App gezielt zu ermitteln. Die Menge des verbleibenden Systemspeichers interessiert mich nicht wirklich.

Die einzige Möglichkeit, an die ich denken konnte, ist eine, die ich nicht mag. Besorgen Sie sich die Menge an Systemspeicher auf der ersten Zeile des Haupt in meiner app, dann speichern Sie es in einer statischen Variablen in einer Klasse Globals dann würde die getCurrentMemUsage gehen so etwas wie dieses

-(long)getCurrentMemUsage 
{ 
    long sysUsage = [self getSystemMemoryUsed]; 
    return sysUsage - [Globals origSysUsage]; 
} 

Dieses einige gravierende Nachteile. Der offensichtlichste für mich ist, dass eine andere App mitten in meinem Upload getötet wird, was sysUsage niedriger als origSysUsage fallen lässt, was zu einer negativen Zahl führt, selbst wenn meine App 10MB Speicher verwendet, was dazu führen könnte, dass meine App 40MB verwendet eine Anfrage und nicht das Maximum von 20MB. Ich könnte es immer einrichten, also klemmt es den Wert zwischen MIN_CHUNK_SIZE und MAX_MEM_USAGE, aber das wäre nur ein Workaround anstelle einer tatsächlichen Lösung.

Wenn es irgendwelche Vorschläge gibt, wie viel Speicher von einer App verwendet wird, oder sogar verschiedene Methoden zur Verwaltung einer dynamischen Chunk-Größe, würde ich es entweder begrüßen.

+0

ich nur 256KB Stücke verwenden würde und mit ihm getan werden. Gibt es einen wesentlichen Vorteil, um größere Brocken zu haben? –

+0

@DavidSchwartz Nur dass es den Upload-Prozess erheblich beschleunigt. Der Benutzer könnte Dateien mit einer Größe von mehr als 1 GB hochladen, so dass es wahnsinnig viele Stücke kosten würde, um sie hochzuladen. Es würde eine Menge Stücke bei 20 MB nehmen, aber immer noch besser als 256 KB (oder einen anderen kleineren Wert). Außerdem benötigen einige Dateien nicht die vollen 20 MB Speicher zum Hochladen (z. B. ein JPEG). Unser Ziel für diese App ist es, so schnell wie möglich in so wenig Anfragen wie möglich hochzuladen, ohne dass der Arbeitsspeicher knapp wird. – nick

+0

zumindest beschleunigte es den Upload-Prozess auf Android, ich bin mir sicher, es würde auf iOS-Geräten sowie – nick

Antwort

0

Jetzt, wie bei jedem Betriebssystem mit virtuellem Speicher, ist es nicht sehr gut, den "verwendeten Speicher" zu bekommen, und es ist notorisch schwierig, ihn zu definieren und zu berechnen.

Glücklicherweise kann Ihr Problem dank des virtuellen Speichermanagers recht einfach gelöst werden: die mmap() C-Funktion. Grundsätzlich ermöglicht es Ihrer App, die Datei virtuell in den Arbeitsspeicher zu laden und sie so zu behandeln, als wäre sie im Arbeitsspeicher. Sie wird jedoch beim Zugriff auf den Speicher tatsächlich ausgetauscht und bei niedrigem Arbeitsspeicher ausgetauscht.

Diese Funktion ist sehr einfach in iOS mit der Cocoa-APIs für sie zu verwenden:

- (void) uploadMyFile:(NSString*)fileName { 
    NSData* fileData = [NSData dataWithContentsOfMappedFile:fileName]; 
    // Work with the data as with any NSData* object. The iOS kernel 
    // will take care of loading the file as needed. 
} 
+0

Würde das Hinzufügen der NSData zu einer POST-Anfrage nicht die gesamte Datei erfordern und sie trotzdem in den Speicher laden? Ich denke, dass ich im Wesentlichen dasselbe mache, indem ich die getBytes-Methode der ALAssetRepresentation verwende. Ich überspringe zu totalBytesRead und lese chunkSize Bytes ein und klebe es dann auf die POST Anfrage. Soweit ich das beurteilen kann, würde das Hinzufügen von fileData zur Anfrage alle Seiten auf einmal erfordern und ich würde immer noch mit der gesamten Datei im Speicher sitzen. Ich hoffe, ich liege falsch, denn deine Lösung sieht wirklich einfach aus :) – nick

+0

Nein, das wäre nicht - das ist die Schönheit von Memory-Mapped-Dateien. Für die technischen Details empfehle ich den Wikipedia-Artikel, mit dem ich verlinkt habe. Ich kann jedoch nicht sagen, ob es Ihr spezifisches Problem löst oder nicht, aber ich rate Ihnen, es zu versuchen. – Krumelur

Verwandte Themen