Re: Managing image loading

2014-02-11 Thread Leonardo
Ok Jens,
my method turned so complicated due to hundreds of relationships, undo,
fileWrappers, copy/paste, new object IDs... That I'm going to do as you say.

I am going to load the image and leave it within the NSView object.

When I delete an NSView containing the image, I put its pointer within the
undo stack, then I release the NSView (which doesn't get deallocated
therefore). Thin way when invoking the undo, I get back all the
relashionships that object had with other objects.

When saving, I write the image's NSData within the filePackage.
When re-loading a file, I read that NSData and create the image.
It sounds linear and clean.

Good luck to myself. I'll let you know.


Regards
-- Leonardo


> Da: Jens Alfke 
> Data: Sat, 8 Feb 2014 16:37:01 -0800
> A: Leonardo 
> Cc: 
> Oggetto: Re: Managing image loading
> 
> 
> On Feb 8, 2014, at 3:58 AM, Leonardo  wrote:
> 
>> When the user imports a new image, I quickly copy the image to a temporary
>> folder, then I add this latest file reference to the document¹s
>> NSFileWrapper.
>> I just create the file¹s fileWrapper using its URL, so I do not read its
>> content and create the fileWrapper by the NSData.
> 
> This seems like a hacky workaround for the kind of temporary storage that
> you'd already get from virtual memory. See below.
> 
>> Why don¹t I add the file¹s NSData to the fileWrapper but I add just its URL
>> reference? Because I don¹t really know whether the fileWrapper uses the disk
>> or keeps the NSData in memory. So in case of a 1GB file I do not engulf the
>> app.
> 
> It's a 64-bit app, presumably, so you have no worries about running out of
> address space. If physical RAM is running low, then the OS will just write
> part of your address space to disk to make room; when you access that address
> space again, it'll read it back in.
> 
> Basically the virtual memory system is going to do what your
> temporary-file-copying solution would have done, only it's doing it more
> efficiently because (a) it only writes it to disk if there's not enough RAM;
> (b) it only copies as much of the data as needed; and (c) it'll free up that
> disk space automatically later on.
> 
> I think I asked this before, but: Do you already have a running app that is
> having performance problems working with large or lots of images? Or are you
> simply imagining that your app might run into these problems, without knowing
> whether that's true? In the latter case, _especially_ if you're a novice
> developer or new to the platform, please put off worrying about performance
> until later.
> 
> ‹Jens



___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Managing image loading

2014-02-08 Thread Jens Alfke

On Feb 8, 2014, at 3:58 AM, Leonardo  wrote:

> When the user imports a new image, I quickly copy the image to a temporary 
> folder, then I add this latest file reference to the document’s NSFileWrapper.
> I just create the file’s fileWrapper using its URL, so I do not read its 
> content and create the fileWrapper by the NSData.

This seems like a hacky workaround for the kind of temporary storage that you'd 
already get from virtual memory. See below.

> Why don’t I add the file’s NSData to the fileWrapper but I add just its URL 
> reference? Because I don’t really know whether the fileWrapper uses the disk 
> or keeps the NSData in memory. So in case of a 1GB file I do not engulf the 
> app.

It's a 64-bit app, presumably, so you have no worries about running out of 
address space. If physical RAM is running low, then the OS will just write part 
of your address space to disk to make room; when you access that address space 
again, it'll read it back in.

Basically the virtual memory system is going to do what your 
temporary-file-copying solution would have done, only it's doing it more 
efficiently because (a) it only writes it to disk if there's not enough RAM; 
(b) it only copies as much of the data as needed; and (c) it'll free up that 
disk space automatically later on.

I think I asked this before, but: Do you already have a running app that is 
having performance problems working with large or lots of images? Or are you 
simply imagining that your app might run into these problems, without knowing 
whether that's true? In the latter case, _especially_ if you're a novice 
developer or new to the platform, please put off worrying about performance 
until later.

—Jens
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Managing image loading

2014-02-08 Thread Kyle Sluder
On Feb 8, 2014, at 3:58 AM, Leonardo  wrote:
> 
> I had to scratch my head at managing the undo, but I found a solution here
> too.
> When the user undo the import of an image, if the images has been never
> saved, so it is still within the temporary folder, I just remove the image
> file reference from the fileWrapper. Instead, if the image has already been
> saved, so it is within the file package, I copy its file to the temporary
> folder and remove its reference from the fileWrapper. So when the user saves
> the doc, the image file get removed from the doc filePackage. And if the
> user invokes the undo, I add the temp image file to the fileWrapper.
> It sounds complicated but it works well.

This will break.

> 
> Why do I use a temporary folder? Because if the user imports an image file
> then he tries to delete the original image file, the OS tells him that he
> can¹t delete that file in use. That could be annoying.

Except the file *is* in use—a reference to it lives on your undo stack. You 
seem not to care about data corruption.

But it turns out this doesn’t matter, because your NSData will have an open 
file descriptor on the image file, so deleting it via Finder won’t actually 
delete the file from disk until the NSData instance is reallocated or your app 
quits.

The only thing that would be problematic would be ejecting the volume the file 
lives on—the OS should warn about that.

So you need to handle the case that the file gets deleted while its data is 
still on the undo stack. You won't be able to swap the file back into place. 
See below for how to address that: 

> Why don¹t I add the file¹s NSData to the fileWrapper but I add just its URL
> reference? Because I don¹t really know whether the fileWrapper uses the disk
> or keeps the NSData in memory. So in case of a 1GB file I do not engulf the
> app.

1. Look up “memory mapping.” You can pass arguments to NSData that control 
whether it maps the image file.

2. The wonderful thing about virtual memory is that it gets paged out to disk.

3. 64-bit apps have oodles of address space (256TB under the current scheme); 
dedicating 1GB of that to a memory-mapped image file is not going to be a 
problem.

--Kyle Sluder

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Managing image loading

2014-02-08 Thread Leonardo
Thank you Jens. I have found the proper way to manage that.
When the user imports a new image, I quickly copy the image to a temporary
folder, then I add this latest file reference to the document¹s
NSFileWrapper.
I just create the file¹s fileWrapper using its URL, so I do not read its
content and create the fileWrapper by the NSData.
When the users saves the document, automatically the filesWrappers get
written to the disk, within the document filePackage.
And when I close the document, I remove the temp folder.
That¹s fine.

I had to scratch my head at managing the undo, but I found a solution here
too.
When the user undo the import of an image, if the images has been never
saved, so it is still within the temporary folder, I just remove the image
file reference from the fileWrapper. Instead, if the image has already been
saved, so it is within the file package, I copy its file to the temporary
folder and remove its reference from the fileWrapper. So when the user saves
the doc, the image file get removed from the doc filePackage. And if the
user invokes the undo, I add the temp image file to the fileWrapper.
It sounds complicated but it works well.

Why do I use a temporary folder? Because if the user imports an image file
then he tries to delete the original image file, the OS tells him that he
can¹t delete that file in use. That could be annoying.
Why don¹t I add the file¹s NSData to the fileWrapper but I add just its URL
reference? Because I don¹t really know whether the fileWrapper uses the disk
or keeps the NSData in memory. So in case of a 1GB file I do not engulf the
app.

I hope I have designed a good architecture.


Regards
-- Leonardo



Da: Jens Alfke 
Data: Tue, 4 Feb 2014 11:47:35 -0800
A: Leonardo 
Cc: 
Oggetto: Re: Managing image loading


On Feb 4, 2014, at 9:03 AM, Leonardo  wrote:

> - When the user imports a new image, I add its NSData to the NSFileWrapper
>[docFileWrapper addRegularFileWithContents:imgData
>preferredFilename:@"image.png"];
> and retain the NSImage. So I can draw the NSImage at any time.

You don't need an NSFileWrapper for that. I would just use NSFileManager to
copy the file, and NSData methods to read/write the file. I have no idea
whether NSFileWrapper caches the file contents in memory or not.

‹Jens


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Managing image loading

2014-02-04 Thread Jens Alfke

On Feb 4, 2014, at 9:03 AM, Leonardo  wrote:

> - When the user imports a new image, I add its NSData to the NSFileWrapper
>[docFileWrapper addRegularFileWithContents:imgData
>preferredFilename:@"image.png"];
> and retain the NSImage. So I can draw the NSImage at any time.

You don't need an NSFileWrapper for that. I would just use NSFileManager to 
copy the file, and NSData methods to read/write the file. I have no idea 
whether NSFileWrapper caches the file contents in memory or not.

—Jens
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Managing image loading

2014-02-04 Thread Leonardo
The images could be of any size and could be thousands. The user decides.
If I understood well, since NSImage does caching, I could:

- When the user imports a new image, I add its NSData to the NSFileWrapper
[docFileWrapper addRegularFileWithContents:imgData
preferredFilename:@"image.png"];
and retain the NSImage. So I can draw the NSImage at any time.

If the user deletes the image, I release the NSImage and remove its NSData
from the fileWrapper.

If the user saves the document, NSDocument invokes
- (NSFileWrapper*)fileWrapperOfType:(NSString*)typeName
error:(NSError**)outError
and saves the filePackage (saving the images' NSData previously added to the
wrapper).
If the user doesn¹t save the document, the filePackage will be left
untouched.

I strongly hope that the NSFileWrapper does caching too, otherwise I could
even end with a fileWrapper large GBs.

Does all of that sound good?

Regards
-- Leonardo



Da: Jens Alfke 
Data: Tue, 4 Feb 2014 07:41:41 -0800
A: Leonardo 
Cc: 
Oggetto: Re: Managing image loading


On Feb 4, 2014, at 3:05 AM, Leonardo  wrote:

> My app displays several images on several pages.
> Since the app displays one page per time, I would like to optimize the
> memory management at loading and displaying the images.

It'd be best to explicitly release/free the images for a page when that page
stops being displayed.

> to reference all the images when opening a document. So, I thought, the
> images get really loaded and displayed at the time I select a given page,
> and discarded (in the cache) when I change page. Does it really work that
> way?

I don't know. NSImage is a very high-level API that does a lot of caching
behind the scenes, and the AppKit team tends to make subtle changes to its
behavior from one release to another. I don't remember seeing anything in
the docs that states that an image's pixmap can be purged to make room. (And
the image itself doesn't know when the app changes pages, so changing pages
won't itself trigger any cleanup.)

If you're concerned about memory usage, NSImage is not the best API to use.
You can get more control by using NSImageRepresentation directly, and even
more by using CGImage.

On the other hand, how large are these images? (Do the math: byte usage =
pixel height x pixel width x 4.) How many pages do you expect documents to
have? Is memory really a concern when people's computers have gigabytes of
RAM and (often) very fast SSDs? Remember, "Premature optimization is the
root of all evil."

> Second question. In case the user imports a new image, I presume I should
> immediately copy the image file within the filePackage then call
> initByReferencingFile.

No, you wait until told to save changes to the document. Consider what
happens if the user decides to close without saving, or revert, or to Save
As to a different file.

I'm not sure of the answer to your file-wrapper question; that's not an API
I've used much.

‹Jens




___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Managing image loading

2014-02-04 Thread Jens Alfke

On Feb 4, 2014, at 3:05 AM, Leonardo  wrote:

> My app displays several images on several pages.
> Since the app displays one page per time, I would like to optimize the
> memory management at loading and displaying the images.

It'd be best to explicitly release/free the images for a page when that page 
stops being displayed.

> to reference all the images when opening a document. So, I thought, the
> images get really loaded and displayed at the time I select a given page,
> and discarded (in the cache) when I change page. Does it really work that
> way?

I don't know. NSImage is a very high-level API that does a lot of caching 
behind the scenes, and the AppKit team tends to make subtle changes to its 
behavior from one release to another. I don't remember seeing anything in the 
docs that states that an image's pixmap can be purged to make room. (And the 
image itself doesn't know when the app changes pages, so changing pages won't 
itself trigger any cleanup.)

If you're concerned about memory usage, NSImage is not the best API to use. You 
can get more control by using NSImageRepresentation directly, and even more by 
using CGImage.

On the other hand, how large are these images? (Do the math: byte usage = pixel 
height x pixel width x 4.) How many pages do you expect documents to have? Is 
memory really a concern when people's computers have gigabytes of RAM and 
(often) very fast SSDs? Remember, "Premature optimization is the root of all 
evil."

> Second question. In case the user imports a new image, I presume I should
> immediately copy the image file within the filePackage then call
> initByReferencingFile.

No, you wait until told to save changes to the document. Consider what happens 
if the user decides to close without saving, or revert, or to Save As to a 
different file.

I'm not sure of the answer to your file-wrapper question; that's not an API 
I've used much.

—Jens
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Managing image loading

2014-02-04 Thread Leonardo
My app displays several images on several pages.
Since the app displays one page per time, I would like to optimize the
memory management at loading and displaying the images.
I thought to save my document as filePackage, put the image files within the
package and use the lazy

image = [[NSImage alloc] initByReferencingFile:path];

to reference all the images when opening a document. So, I thought, the
images get really loaded and displayed at the time I select a given page,
and discarded (in the cache) when I change page. Does it really work that
way?

Second question. In case the user imports a new image, I presume I should
immediately copy the image file within the filePackage then call
initByReferencingFile. Should I use

imgFileWrap = [[NSFileWrapper alloc] initWithURL:url options:
NSFileWrapperReadingWithoutMapping error:&err];
[documentFileWrapper addFileWrapper: imgFileWrap];

 or should I simply copy the file image within the filePackage with the
following?

[[NSFileManager defaultManager] copyItemAtPath:src toPath:dst
error:nil];


Regards
-- Leonardo


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com