Overview
Comment: | OFStream: Cache small reads to reduce syscalls
In some situations, this is 50x faster. |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
a7d66e7ab2c0bd991f9271f95a3ce5e3 |
User & Date: | js on 2016-05-05 19:54:55 |
Other Links: | manifest | tags |
Context
2016-05-06
| ||
14:09 | OFZIPArchiveEntry: Add generalPurposeBitFlag check-in: 41e83e895c user: js tags: trunk | |
2016-05-05
| ||
19:54 | OFStream: Cache small reads to reduce syscalls check-in: a7d66e7ab2 user: js tags: trunk | |
17:05 | OFTLSSocket: Fix wrong protocol for delegate check-in: 55dc5a174c user: js tags: trunk | |
Changes
Modified src/OFSeekableStream.m from [4427169ba3] to [fd840df49d].
︙ | ︙ | |||
50 51 52 53 54 55 56 | { if (whence == SEEK_CUR) offset -= _readBufferLength; offset = [self lowlevelSeekToOffset: offset whence: whence]; | | | | 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | { if (whence == SEEK_CUR) offset -= _readBufferLength; offset = [self lowlevelSeekToOffset: offset whence: whence]; [self freeMemory: _readBufferMemory]; _readBuffer = _readBufferMemory = NULL; _readBufferLength = 0; return offset; } @end |
Modified src/OFStream.h from [87f1020ea1] to [f5d7e92017].
︙ | ︙ | |||
90 91 92 93 94 95 96 | OFReadyForReadingObserving, OFReadyForWritingObserving, #endif OFCopying> { #if !defined(OF_SEEKABLE_STREAM_M) && !defined(OF_TCP_SOCKET_M) @private #endif | | | 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 | OFReadyForReadingObserving, OFReadyForWritingObserving, #endif OFCopying> { #if !defined(OF_SEEKABLE_STREAM_M) && !defined(OF_TCP_SOCKET_M) @private #endif char *_readBuffer, *_readBufferMemory, *_writeBuffer; size_t _readBufferLength, _writeBufferLength; bool _writeBuffered, _waitingForDelimiter; @protected bool _blocking; } /*! |
︙ | ︙ |
Modified src/OFStream.m from [fefe498c92] to [3e396d5660].
︙ | ︙ | |||
45 46 47 48 49 50 51 52 53 54 55 56 57 58 | #import "OFInvalidFormatException.h" #import "OFNotImplementedException.h" #import "OFOutOfRangeException.h" #import "OFSetOptionFailedException.h" #import "of_asprintf.h" @implementation OFStream @synthesize OF_isWaitingForDelimiter = _waitingForDelimiter; #ifndef OF_WINDOWS + (void)initialize { if (self == [OFStream class]) | > > | 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | #import "OFInvalidFormatException.h" #import "OFNotImplementedException.h" #import "OFOutOfRangeException.h" #import "OFSetOptionFailedException.h" #import "of_asprintf.h" #define MIN_READ_SIZE 512 @implementation OFStream @synthesize OF_isWaitingForDelimiter = _waitingForDelimiter; #ifndef OF_WINDOWS + (void)initialize { if (self == [OFStream class]) |
︙ | ︙ | |||
108 109 110 111 112 113 114 | return [self lowlevelIsAtEndOfStream]; } - (size_t)readIntoBuffer: (void*)buffer length: (size_t)length { | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | < < < < < < | | 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 | return [self lowlevelIsAtEndOfStream]; } - (size_t)readIntoBuffer: (void*)buffer length: (size_t)length { if (_readBufferLength == 0) { /* * For small sizes, it is cheaper to read more and cache the * remainder - even if that means more copying of data - than * to do a syscall for every read. */ if (length < MIN_READ_SIZE) { char tmp[MIN_READ_SIZE], *readBuffer; size_t bytesRead; bytesRead = [self lowlevelReadIntoBuffer: tmp length: MIN_READ_SIZE]; if (bytesRead > length) { memcpy(buffer, tmp, length); readBuffer = [self allocMemoryWithSize: bytesRead - length]; memcpy(readBuffer, tmp + length, bytesRead - length); _readBuffer = _readBufferMemory = readBuffer; _readBufferLength = bytesRead - length; return length; } else { memcpy(buffer, tmp, bytesRead); return bytesRead; } } return [self lowlevelReadIntoBuffer: buffer length: length]; } if (length >= _readBufferLength) { size_t ret = _readBufferLength; memcpy(buffer, _readBuffer, _readBufferLength); [self freeMemory: _readBufferMemory]; _readBuffer = _readBufferMemory = NULL; _readBufferLength = 0; return ret; } else { memcpy(buffer, _readBuffer, length); _readBuffer += length; _readBufferLength -= length; return length; } } - (void)readIntoBuffer: (void*)buffer |
︙ | ︙ | |||
566 567 568 569 570 571 572 | if (i > 0 && _readBuffer[i - 1] == '\r') retLength--; ret = [OFString stringWithCString: _readBuffer encoding: encoding length: retLength]; | < < < < < < < | | 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 | if (i > 0 && _readBuffer[i - 1] == '\r') retLength--; ret = [OFString stringWithCString: _readBuffer encoding: encoding length: retLength]; _readBuffer += i + 1; _readBufferLength -= i + 1; _waitingForDelimiter = false; return ret; } } } |
︙ | ︙ | |||
602 603 604 605 606 607 608 | if (retLength > 0 && _readBuffer[retLength - 1] == '\r') retLength--; ret = [OFString stringWithCString: _readBuffer encoding: encoding length: retLength]; | | | | 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 | if (retLength > 0 && _readBuffer[retLength - 1] == '\r') retLength--; ret = [OFString stringWithCString: _readBuffer encoding: encoding length: retLength]; [self freeMemory: _readBufferMemory]; _readBuffer = _readBufferMemory = NULL; _readBufferLength = 0; _waitingForDelimiter = false; return ret; } bufferLength = [self lowlevelReadIntoBuffer: buffer |
︙ | ︙ | |||
640 641 642 643 644 645 646 | size_t rl = retLength; ret = [OFString stringWithCString: rcs encoding: encoding length: rl]; } @catch (id e) { | > | | > | | | | | | > | | > > > > | > > | | > | | < < | < < < | > > | > | 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 | size_t rl = retLength; ret = [OFString stringWithCString: rcs encoding: encoding length: rl]; } @catch (id e) { if (bufferLength > 0) { /* * Append data to _readBuffer * to prevent loss of data due * to wrong encoding. */ readBuffer = [self allocMemoryWithSize: _readBufferLength + bufferLength]; memcpy(readBuffer, _readBuffer, _readBufferLength); memcpy(readBuffer + _readBufferLength, buffer, bufferLength); [self freeMemory: _readBufferMemory]; _readBuffer = readBuffer; _readBufferMemory = readBuffer; _readBufferLength += bufferLength; } @throw e; } @finally { [self freeMemory: retCString]; } readBuffer = [self allocMemoryWithSize: bufferLength - i - 1]; if (readBuffer != NULL) memcpy(readBuffer, buffer + i + 1, bufferLength - i - 1); [self freeMemory: _readBufferMemory]; _readBuffer = _readBufferMemory = readBuffer; _readBufferLength = bufferLength - i - 1; _waitingForDelimiter = false; return ret; } } /* There was no newline or \0 */ if (bufferLength > 0) { readBuffer = [self allocMemoryWithSize: _readBufferLength + bufferLength]; memcpy(readBuffer, _readBuffer, _readBufferLength); memcpy(readBuffer + _readBufferLength, buffer, bufferLength); [self freeMemory: _readBufferMemory]; _readBuffer = _readBufferMemory = readBuffer; _readBufferLength += bufferLength; } } @finally { [self freeMemory: buffer]; } _waitingForDelimiter = true; return nil; } |
︙ | ︙ | |||
785 786 787 788 789 790 791 | delimiterLength = 1; ret = [OFString stringWithCString: _readBuffer encoding: encoding length: i + 1 - delimiterLength]; | < < < < < < < | | 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 | delimiterLength = 1; ret = [OFString stringWithCString: _readBuffer encoding: encoding length: i + 1 - delimiterLength]; _readBuffer += i + 1; _readBufferLength -= i + 1; _waitingForDelimiter = false; return ret; } } } |
︙ | ︙ | |||
816 817 818 819 820 821 822 | return nil; } ret = [OFString stringWithCString: _readBuffer encoding: encoding length: _readBufferLength]; | | | | 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 | return nil; } ret = [OFString stringWithCString: _readBuffer encoding: encoding length: _readBufferLength]; [self freeMemory: _readBufferMemory]; _readBuffer = _readBufferMemory = NULL; _readBufferLength = 0; _waitingForDelimiter = false; return ret; } bufferLength = [self lowlevelReadIntoBuffer: buffer |
︙ | ︙ | |||
870 871 872 873 874 875 876 | readBuffer = [self allocMemoryWithSize: bufferLength - i - 1]; if (readBuffer != NULL) memcpy(readBuffer, buffer + i + 1, bufferLength - i - 1); | | | > | | < < | < < < | > > | > | 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 | readBuffer = [self allocMemoryWithSize: bufferLength - i - 1]; if (readBuffer != NULL) memcpy(readBuffer, buffer + i + 1, bufferLength - i - 1); [self freeMemory: _readBufferMemory]; _readBuffer = _readBufferMemory = readBuffer; _readBufferLength = bufferLength - i - 1; _waitingForDelimiter = false; return ret; } } /* Neither the delimiter nor \0 was found */ if (bufferLength > 0) { readBuffer = [self allocMemoryWithSize: _readBufferLength + bufferLength]; memcpy(readBuffer, _readBuffer, _readBufferLength); memcpy(readBuffer + _readBufferLength, buffer, bufferLength); [self freeMemory: _readBufferMemory]; _readBuffer = _readBufferMemory = readBuffer; _readBufferLength += bufferLength; } } @finally { [self freeMemory: buffer]; } _waitingForDelimiter = true; return nil; } |
︙ | ︙ | |||
1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 | [OFRunLoop OF_cancelAsyncRequestsForObject: self]; } #endif - (void)unreadFromBuffer: (const void*)buffer length: (size_t)length { if (length > SIZE_MAX - _readBufferLength) @throw [OFOutOfRangeException exception]; | > > < | | | < > > | 1518 1519 1520 1521 1522 1523 1524 1525 1526 1527 1528 1529 1530 1531 1532 1533 1534 1535 1536 1537 1538 1539 1540 1541 1542 1543 | [OFRunLoop OF_cancelAsyncRequestsForObject: self]; } #endif - (void)unreadFromBuffer: (const void*)buffer length: (size_t)length { char *readBuffer; if (length > SIZE_MAX - _readBufferLength) @throw [OFOutOfRangeException exception]; readBuffer = [self allocMemoryWithSize: _readBufferLength + length]; memcpy(readBuffer, buffer, length); memcpy(readBuffer + length, _readBuffer, _readBufferLength); [self freeMemory: _readBuffer]; _readBuffer = _readBufferMemory = readBuffer; _readBufferLength += length; } - (void)close { OF_UNRECOGNIZED_SELECTOR } @end |