I’ve been prototyping an internal tool that receives and displays lots
of text data. I wanted to display this kind of like how Terminal.app
continuously appends text and keeps scrolling to the bottom as more
data is added.

I used a stock NSTextView and keep appending to the backing NSTextStorage.
I found a solution to autoscrolling on stackoverflow which I incorporated.
http://stackoverflow.com/questions/15546808/scrolling-nstextview-to-bottom


- (void) postLogEvent:(NSString*)log_message
{
        BOOL scroll = (NSMaxY([[self logStreamTextView] visibleRect]) ==
NSMaxY([[self logStreamTextView] bounds]));
        [[[[self logStreamTextView] textStorage] mutableString]
appendString:log_message];
        if (scroll) // Scroll to end of the textview contents
        {
                [[self logStreamTextView] scrollRangeToVisible: 
NSMakeRange([[[self
logStreamTextView] string] length], 0)];
        }
}

This works, but I encountered two problems when the data set gets large.

1) Somewhere after 40,000 lines of text, the application starts
becoming unresponsive. Around 50k-60k, the application feels hung and
I have to force kill it. I figured out that the bottleneck was in
scrollRangeToVisible call.

I’ve posted 3 screenshots from Instruments here:
https://picasaweb.google.com/ewmailing/AutoscrollingNSTextViewTrace#5962576581630914370

2) If I disable autoscrolling, performance is fine. I got to around
150,000 lines without any problems. But at some point later (my test
runs for several hours so I usually leave it unattended and it can
generate a million lines, so I don’t know exactly when), Cocoa raised
an exception at:

-[NSBigMutableString replaceCharactersInRange:withString:]: nil argument
(Full exception trace is below for interest.)


So I was wondering if there were any better techniques to avoid my two
problems or how I should go about resolving them. Since this is an
internal tool to help something else, I'm looking for simple/quick
solutions, though for my own curiosity, I also do wonder what the
proper solution is.


Thanks,
Eric


An uncaught exception was raised
2013-12-28 07:41:50.304 Test262LogClient[44722:303] ***
-[NSBigMutableString replaceCharactersInRange:withString:]: nil
argument
2013-12-28 07:41:50.305 Test262LogClient[44722:303] (
        0   CoreFoundation                      0x00007fff92d6e41c
__exceptionPreprocess + 172
        1   libobjc.A.dylib                     0x00007fff8b7ebe75
objc_exception_throw + 43
        2   CoreFoundation                      0x00007fff92d6e2cc
+[NSException raise:format:] + 204
        3   Foundation                          0x00007fff928430e4
-[NSBigMutableString replaceCharactersInRange:withString:] + 111
        4   Foundation                          0x00007fff9284185e
-[NSConcreteMutableAttributedString
replaceCharactersInRange:withString:] + 295
        5   AppKit                              0x00007fff893ff136
-[NSConcreteTextStorage replaceCharactersInRange:withString:] + 77
        6   Test262LogClient                    0x00000001000020bf
-[LogStreamWindowController postLogEvent:] + 591
        7   Test262LogClient                    0x0000000100010533
__69-[ResolveForLogStreamDelegate
connectToServerAndSendStreamDirective:]_block_invoke_256 + 67
        8   libdispatch.dylib                   0x00007fff8c3e11d7
_dispatch_call_block_and_release + 12
        9   libdispatch.dylib                   0x00007fff8c3de2ad
_dispatch_client_callout + 8
        10  libdispatch.dylib                   0x00007fff8c3e5f03
_dispatch_main_queue_callback_4CF + 333
        11  CoreFoundation                      0x00007fff92cd5839
__CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9
        12  CoreFoundation                      0x00007fff92c90b14
__CFRunLoopRun + 1636
        13  CoreFoundation                      0x00007fff92c90275
CFRunLoopRunSpecific + 309
        14  HIToolbox                           0x00007fff8b9baf0d
RunCurrentEventLoopInMode + 226
        15  HIToolbox                           0x00007fff8b9bacb7
ReceiveNextEventCommon + 479
        16  HIToolbox                           0x00007fff8b9baabc
_BlockUntilNextEventMatchingListInModeWithFilter + 65
        17  AppKit                              0x00007fff891a228e 
_DPSNextEvent + 1434
        18  AppKit                              0x00007fff891a18db
-[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] + 122
        19  AppKit                              0x00007fff891959cc
-[NSApplication run] + 553
        20  AppKit                              0x00007fff89180803
NSApplicationMain + 940
        21  Test262LogClient                    0x000000010005f962 main + 34
        22  libdyld.dylib                       0x00007fff8d6245fd start + 1
        23  ???                                 0x0000000000000003 0x0 + 3
)
2013-12-28 07:41:50.307 Test262LogClient[44722:303] *** Terminating
app due to uncaught exception 'NSInvalidArgumentException', reason:
'*** -[NSBigMutableString replaceCharactersInRange:withString:]: nil
argument'
*** First throw call stack:
(
        0   CoreFoundation                      0x00007fff92d6e41c
__exceptionPreprocess + 172
        1   libobjc.A.dylib                     0x00007fff8b7ebe75
objc_exception_throw + 43
        2   CoreFoundation                      0x00007fff92d6e2cc
+[NSException raise:format:] + 204
        3   Foundation                          0x00007fff928430e4
-[NSBigMutableString replaceCharactersInRange:withString:] + 111
        4   Foundation                          0x00007fff9284185e
-[NSConcreteMutableAttributedString
replaceCharactersInRange:withString:] + 295
        5   AppKit                              0x00007fff893ff136
-[NSConcreteTextStorage replaceCharactersInRange:withString:] + 77
        6   Test262LogClient                    0x00000001000020bf
-[LogStreamWindowController postLogEvent:] + 591
        7   Test262LogClient                    0x0000000100010533
__69-[ResolveForLogStreamDelegate
connectToServerAndSendStreamDirective:]_block_invoke_256 + 67
        8   libdispatch.dylib                   0x00007fff8c3e11d7
_dispatch_call_block_and_release + 12
        9   libdispatch.dylib                   0x00007fff8c3de2ad
_dispatch_client_callout + 8
        10  libdispatch.dylib                   0x00007fff8c3e5f03
_dispatch_main_queue_callback_4CF + 333
        11  CoreFoundation                      0x00007fff92cd5839
__CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9
        12  CoreFoundation                      0x00007fff92c90b14
__CFRunLoopRun + 1636
        13  CoreFoundation                      0x00007fff92c90275
CFRunLoopRunSpecific + 309
        14  HIToolbox                           0x00007fff8b9baf0d
RunCurrentEventLoopInMode + 226
        15  HIToolbox                           0x00007fff8b9bacb7
ReceiveNextEventCommon + 479
        16  HIToolbox                           0x00007fff8b9baabc
_BlockUntilNextEventMatchingListInModeWithFilter + 65
        17  AppKit                              0x00007fff891a228e 
_DPSNextEvent + 1434
        18  AppKit                              0x00007fff891a18db
-[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] + 122
        19  AppKit                              0x00007fff891959cc
-[NSApplication run] + 553
        20  AppKit                              0x00007fff89180803
NSApplicationMain + 940
        21  Test262LogClient                    0x000000010005f962 main + 34
        22  libdyld.dylib                       0x00007fff8d6245fd start + 1
        23  ???                                 0x0000000000000003 0x0 + 3
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)

_______________________________________________

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

Reply via email to