Skip to content

Commit

Permalink
Don't store ascii data in NSData because it takes forever to dealloc.…
Browse files Browse the repository at this point in the history
… Instead, use a 128 byte static buffer if possible.
  • Loading branch information
gnachman committed Mar 7, 2014
1 parent 272d5bc commit fd03881
Show file tree
Hide file tree
Showing 12 changed files with 99 additions and 35 deletions.
7 changes: 5 additions & 2 deletions PTYSession.m
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#import "VT100Screen.h"
#import "VT100ScreenMark.h"
#import "VT100Terminal.h"
#import "VT100Token.h"
#import "WindowControllerInterface.h"
#import "iTerm.h"
#import "iTermApplicationDelegate.h"
Expand Down Expand Up @@ -4722,9 +4723,11 @@ - (void)screenDidAppendStringToCurrentLine:(NSString *)string {
[self appendStringToTriggerLine:string];
}

- (void)screenDidAppendAsciiDataToCurrentLine:(NSData *)asciiData {
- (void)screenDidAppendAsciiDataToCurrentLine:(AsciiData *)asciiData {
if ([_triggers count]) {
NSString *string = [[NSString alloc] initWithData:asciiData encoding:NSASCIIStringEncoding];
NSString *string = [[[NSString alloc] initWithBytes:asciiData->buffer
length:asciiData->length
encoding:NSASCIIStringEncoding] autorelease];
[self screenDidAppendStringToCurrentLine:string];
}
}
Expand Down
4 changes: 2 additions & 2 deletions TmuxHistoryParser.m
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,8 @@ - (NSData *)dataForHistoryLine:(NSString *)hist
VT100Token *token = CVectorGetObject(&vector, i);
[terminal executeToken:token];
NSString *string = token.isStringType ? token.string : nil;
if (!string && token.isStringType && token.data) {
string = [[[NSString alloc] initWithData:token.data encoding:NSASCIIStringEncoding] autorelease];
if (!string && token->type == VT100_ASCIISTRING) {
string = [token stringForAsciiData];
}

if (string) {
Expand Down
7 changes: 5 additions & 2 deletions VT100Parser.m
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,11 @@ - (BOOL)addNextParsedTokensToVector:(CVector *)vector {

token->savingData = _saveData;
if (token->type != VT100_WAIT && token->type != VT100CC_NULL) {
if (_saveData || token->type == VT100_ASCIISTRING) {
token.data = [NSData dataWithBytes:position length:length];
if (_saveData) {
token.savedData = [NSData dataWithBytes:position length:length];
}
if (token->type == VT100_ASCIISTRING) {
[token setAsciiBytes:(char *)position length:length];
}
CVectorAppend(vector, token);

Expand Down
3 changes: 2 additions & 1 deletion VT100Screen.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#import "SCPPath.h"
#import "VT100ScreenDelegate.h"
#import "VT100Terminal.h"
#import "VT100Token.h"

@class DVR;
@class iTermGrowlDelegate;
Expand Down Expand Up @@ -147,7 +148,7 @@ extern int kVT100ScreenMinRows;
// around modes are respected, the cursor is advanced, the screen may be scrolled, and the line
// buffer may change.
- (void)appendStringAtCursor:(NSString *)string;
- (void)appendAsciiDataAtCursor:(NSData *)asciiData;
- (void)appendAsciiDataAtCursor:(AsciiData *)asciiData;

// This is a hacky thing that moves the cursor to the next line, not respecting scroll regions.
// It's used for the tmux status screen.
Expand Down
20 changes: 11 additions & 9 deletions VT100Screen.m
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#import "iTermExpose.h"
#import "iTermGrowlDelegate.h"
#import "iTermSelection.h"
#import "VT100Token.h"

#import <apr-1/apr_base64.h>
#include <string.h>
Expand Down Expand Up @@ -761,14 +762,14 @@ - (void)clearScrollbackBuffer
[self reloadMarkCache];
}

- (void)appendAsciiDataAtCursor:(NSData *)asciiData
- (void)appendAsciiDataAtCursor:(AsciiData *)asciiData
{
int len = [asciiData length];
int len = asciiData->length;
if (len < 1 || !asciiData) {
return;
}

char firstChar = ((char *)asciiData.bytes)[0];
char firstChar = asciiData->buffer[0];

DLog(@"appendAsciiDataAtCursor: %ld chars starting with %c at x=%d, y=%d, line=%d",
(unsigned long)len,
Expand All @@ -783,15 +784,15 @@ - (void)appendAsciiDataAtCursor:(NSData *)asciiData
screen_char_t *dynamicBuffer = 0;
screen_char_t *buffer;

const char *bytes = [asciiData bytes];
const char *bytes = asciiData->buffer;
assert(terminal_);
screen_char_t fg = [terminal_ foregroundColorCode];
screen_char_t bg = [terminal_ backgroundColorCode];

BOOL zeroed = NO;
if ([asciiData length] > kStaticBufferElements) {
if (asciiData->length > kStaticBufferElements) {
zeroed = YES;
buffer = dynamicBuffer = (screen_char_t *) calloc([asciiData length],
buffer = dynamicBuffer = (screen_char_t *) calloc(asciiData->length,
sizeof(screen_char_t));
assert(dynamicBuffer);
if (!buffer) {
Expand Down Expand Up @@ -1892,10 +1893,11 @@ - (void)terminalAppendString:(NSString *)string {
[delegate_ screenDidAppendStringToCurrentLine:string];
}

- (void)terminalAppendAsciiData:(NSData *)asciiData {
- (void)terminalAppendAsciiData:(AsciiData *)asciiData {
if (collectInputForPrinting_) {
NSString *string = [[[NSString alloc] initWithData:asciiData
encoding:NSASCIIStringEncoding] autorelease];
NSString *string = [[[NSString alloc] initWithBytes:asciiData->buffer
length:asciiData->length
encoding:NSASCIIStringEncoding] autorelease];
[self terminalAppendString:string];
return;
} else {
Expand Down
3 changes: 2 additions & 1 deletion VT100ScreenDelegate.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#import <Cocoa/Cocoa.h>
#import "PTYTextViewDataSource.h"
#import "VT100Token.h"

@class VT100RemoteHost;
@class iTermColorMap;
Expand Down Expand Up @@ -33,7 +34,7 @@

// Called after text was added to the current line. Can be used to check triggers.
- (void)screenDidAppendStringToCurrentLine:(NSString *)string;
- (void)screenDidAppendAsciiDataToCurrentLine:(NSData *)asciiData;
- (void)screenDidAppendAsciiDataToCurrentLine:(AsciiData *)asciiData;

// Change the cursor's appearance.
- (void)screenSetCursorBlinking:(BOOL)blink;
Expand Down
6 changes: 3 additions & 3 deletions VT100Terminal.m
Original file line number Diff line number Diff line change
Expand Up @@ -961,7 +961,7 @@ - (void)executeToken:(VT100Token *)token {
receivingFile_ = NO;
return;
} else if (token->type == VT100_ASCIISTRING) {
[delegate_ terminalDidReceiveBase64FileData:token.string];
[delegate_ terminalDidReceiveBase64FileData:[token stringForAsciiData]];
return;
} else if (token->type == VT100CC_CR ||
token->type == VT100CC_LF ||
Expand All @@ -981,7 +981,7 @@ - (void)executeToken:(VT100Token *)token {
// Append text to clipboard except for initial command that turns on copying to
// the clipboard.

[delegate_ terminalAppendDataToPasteboard:token.data];
[delegate_ terminalAppendDataToPasteboard:token.savedData];
}
}

Expand Down Expand Up @@ -1013,7 +1013,7 @@ - (void)executeToken:(VT100Token *)token {
[delegate_ terminalAppendString:token.string];
break;
case VT100_ASCIISTRING:
[delegate_ terminalAppendAsciiData:token.data];
[delegate_ terminalAppendAsciiData:token.asciiData];
break;

case VT100_UNKNOWNCHAR:
Expand Down
3 changes: 2 additions & 1 deletion VT100TerminalDelegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
//

#import <Foundation/Foundation.h>
#import "VT100Token.h"

typedef enum {
MOUSE_REPORTING_NONE = -1,
Expand All @@ -33,7 +34,7 @@ typedef enum {
@protocol VT100TerminalDelegate
// Append a string at the cursor's position and advance the cursor, scrolling if necessary.
- (void)terminalAppendString:(NSString *)string;
- (void)terminalAppendAsciiData:(NSData *)asciiData;
- (void)terminalAppendAsciiData:(AsciiData *)asciiData;

// Play/display the bell.
- (void)terminalRingBell;
Expand Down
21 changes: 19 additions & 2 deletions VT100Token.h
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,15 @@ typedef struct {
int subCount[VT100CSIPARAM_MAX];
} CSIParam;

// Tokens with type VT100_ASCIISTRING are stored in |asciiData| with this type.
// |buffer| will point at |staticBuffer| or a malloc()ed buffer, depending on
// |length|.
typedef struct {
char *buffer;
int length;
char staticBuffer[128];
} AsciiData;

@interface VT100Token : iTermPooledObject {
@public
VT100TerminalTokenType type;
Expand All @@ -186,8 +195,8 @@ typedef struct {
// For VT100_STRING
@property(nonatomic, retain) NSString *string;

// For VT100_ASCIISTRING and when saving data.
@property(nonatomic, retain) NSData *data;
// For saved data (when copying to clipboard)
@property(nonatomic, retain) NSData *savedData;

// For XTERMCC_SET_KVP.
@property(nonatomic, retain) NSString *kvpKey;
Expand All @@ -205,7 +214,15 @@ typedef struct {
// Is this a string or ascii string?
@property(nonatomic, readonly) BOOL isStringType;

// For ascii strings (type==VT100_ASCIISTRING).
@property(nonatomic, readonly) AsciiData *asciiData;

+ (instancetype)token;
+ (instancetype)tokenForControlCharacter:(unsigned char)controlCharacter;

- (void)setAsciiBytes:(char *)bytes length:(int)length;

// Returns a string for |asciiData|, for convenience (this is slow).
- (NSString *)stringForAsciiData;

@end
36 changes: 33 additions & 3 deletions VT100Token.m
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@ @interface VT100Token ()
@property(nonatomic, readwrite) CSIParam *csi;
@end

@implementation VT100Token
@implementation VT100Token {
AsciiData _asciiData;
}

+ (void)initialize {
gPool = [[iTermObjectPool alloc] initWithClass:self collections:10 objectsPerCollection:100];
Expand Down Expand Up @@ -54,8 +56,14 @@ - (void)destroyPooledObject {
[_kvpValue release];
_kvpValue = nil;

[_data release];
_data = nil;
[_savedData release];
_savedData = nil;

if (_asciiData.buffer != _asciiData.staticBuffer) {
free(_asciiData.buffer);
}
_asciiData.buffer = NULL;
_asciiData.length = 0;

type = 0;
code = 0;
Expand All @@ -80,4 +88,26 @@ - (BOOL)isStringType {
return (type == VT100_STRING || type == VT100_ASCIISTRING);
}

- (void)setAsciiBytes:(char *)bytes length:(int)length {
assert(_asciiData.buffer == NULL);

_asciiData.length = length;
if (length > sizeof(_asciiData.staticBuffer)) {
_asciiData.buffer = malloc(length);
} else {
_asciiData.buffer = _asciiData.staticBuffer;
}
memcpy(_asciiData.buffer, bytes, length);
}

- (AsciiData *)asciiData {
return &_asciiData;
}

- (NSString *)stringForAsciiData {
return [[[NSString alloc] initWithBytes:_asciiData.buffer
length:_asciiData.length
encoding:NSASCIIStringEncoding] autorelease];
}

@end
17 changes: 11 additions & 6 deletions iTermObjectPool.m
Original file line number Diff line number Diff line change
Expand Up @@ -137,16 +137,21 @@ - (iTermPooledObject *)pooledObject {
return [[_class alloc] initWithPool:self collectionNumber:startIndex];
}

- (void)synchronizedRecycleObject:(iTermPooledObject *)obj
toCollection:(ObjectCollection *)collection {
if (collection->count < _objectsPerCollection) {
[obj destroyPooledObject];
collection->objects[collection->count++] = obj;
} else {
[obj release];
}
}

- (void)recycleObject:(iTermPooledObject *)obj {
int collectionIndex = [obj poolCollectionNumber];
ObjectCollection *collection = _collections[collectionIndex];
dispatch_sync(collection->queue, ^{
if (collection->count < _objectsPerCollection) {
[obj destroyPooledObject];
collection->objects[collection->count++] = obj;
} else {
[obj release];
}
[self synchronizedRecycleObject:obj toCollection:collection];
});
}

Expand Down
7 changes: 4 additions & 3 deletions iTermTests/VT100ScreenTest.m
Original file line number Diff line number Diff line change
Expand Up @@ -421,9 +421,10 @@ - (void)screenDidAppendStringToCurrentLine:(NSString *)string {
[triggerLine_ appendString:string];
}

- (void)screenDidAppendAsciiDataToCurrentLine:(NSData *)asciiData {
[self screenDidAppendStringToCurrentLine:[[[NSString alloc] initWithData:asciiData
encoding:NSASCIIStringEncoding]
- (void)screenDidAppendAsciiDataToCurrentLine:(AsciiData *)asciiData {
[self screenDidAppendStringToCurrentLine:[[[NSString alloc] initWithBytes:asciiData->buffer
length:asciiData->length
encoding:NSASCIIStringEncoding]
autorelease]];
}

Expand Down

0 comments on commit fd03881

Please sign in to comment.