Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | For the unix VFS, avoid an unnecessary stat() system call prior to opening any file in the common case where there are no unused file descriptors. |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
3075cfa07489eaf13cb9a2760e2391e7 |
User & Date: | drh 2017-08-18 16:09:52 |
Context
2017-08-18
| ||
21:14 | Size and performance optimization the readDbPage() routine in the pager. check-in: ca9e1875 user: drh tags: trunk | |
16:09 | For the unix VFS, avoid an unnecessary stat() system call prior to opening any file in the common case where there are no unused file descriptors. check-in: 3075cfa0 user: drh tags: trunk | |
14:34 | Combine the OP_CreateTable and OP_CreateIndex opcodes of the bytecode engine into a single OP_CreateBtree opcode. This simplifies the implementation and makes the bytecode programs clearer. check-in: eb1202b5 user: drh tags: trunk | |
Changes
Changes to src/os_unix.c.
206 206 sqlite3_vfs *pVfs; /* The VFS that created this unixFile */ 207 207 unixInodeInfo *pInode; /* Info about locks on this inode */ 208 208 int h; /* The file descriptor */ 209 209 unsigned char eFileLock; /* The type of lock held on this fd */ 210 210 unsigned short int ctrlFlags; /* Behavioral bits. UNIXFILE_* flags */ 211 211 int lastErrno; /* The unix errno from last I/O error */ 212 212 void *lockingContext; /* Locking style specific state */ 213 - UnixUnusedFd *pUnused; /* Pre-allocated UnixUnusedFd */ 213 + UnixUnusedFd *pPreallocatedUnused; /* Pre-allocated UnixUnusedFd */ 214 214 const char *zPath; /* Name of the file */ 215 215 unixShm *pShm; /* Shared memory segment information */ 216 216 int szChunk; /* Configured by FCNTL_CHUNK_SIZE */ 217 217 #if SQLITE_MAX_MMAP_SIZE>0 218 218 int nFetchOut; /* Number of outstanding xFetch refs */ 219 219 sqlite3_int64 mmapSize; /* Usable size of mapping at pMapRegion */ 220 220 sqlite3_int64 mmapSizeActual; /* Actual size of mapping at pMapRegion */ ................................................................................ 1116 1116 char aSemName[MAX_PATHNAME+2]; /* Name of that semaphore */ 1117 1117 #endif 1118 1118 }; 1119 1119 1120 1120 /* 1121 1121 ** A lists of all unixInodeInfo objects. 1122 1122 */ 1123 -static unixInodeInfo *inodeList = 0; 1123 +static unixInodeInfo *inodeList = 0; /* All unixInodeInfo objects */ 1124 +static unsigned int nUnusedFd = 0; /* Total unused file descriptors */ 1124 1125 1125 1126 /* 1126 1127 ** 1127 1128 ** This function - unixLogErrorAtLine(), is only ever called via the macro 1128 1129 ** unixLogError(). 1129 1130 ** 1130 1131 ** It is invoked after an error occurs in an OS function and errno has been ................................................................................ 1226 1227 unixInodeInfo *pInode = pFile->pInode; 1227 1228 UnixUnusedFd *p; 1228 1229 UnixUnusedFd *pNext; 1229 1230 for(p=pInode->pUnused; p; p=pNext){ 1230 1231 pNext = p->pNext; 1231 1232 robust_close(pFile, p->fd, __LINE__); 1232 1233 sqlite3_free(p); 1234 + nUnusedFd--; 1233 1235 } 1234 1236 pInode->pUnused = 0; 1235 1237 } 1236 1238 1237 1239 /* 1238 1240 ** Release a unixInodeInfo structure previously allocated by findInodeInfo(). 1239 1241 ** ................................................................................ 1258 1260 if( pInode->pNext ){ 1259 1261 assert( pInode->pNext->pPrev==pInode ); 1260 1262 pInode->pNext->pPrev = pInode->pPrev; 1261 1263 } 1262 1264 sqlite3_free(pInode); 1263 1265 } 1264 1266 } 1267 + assert( inodeList!=0 || nUnusedFd==0 ); 1265 1268 } 1266 1269 1267 1270 /* 1268 1271 ** Given a file descriptor, locate the unixInodeInfo object that 1269 1272 ** describes that file descriptor. Create a new one if necessary. The 1270 1273 ** return value might be uninitialized if an error occurs. 1271 1274 ** ................................................................................ 1327 1330 memset(&fileId, 0, sizeof(fileId)); 1328 1331 fileId.dev = statbuf.st_dev; 1329 1332 #if OS_VXWORKS 1330 1333 fileId.pId = pFile->pId; 1331 1334 #else 1332 1335 fileId.ino = (u64)statbuf.st_ino; 1333 1336 #endif 1337 + assert( inodeList!=0 || nUnusedFd==0 ); 1334 1338 pInode = inodeList; 1335 1339 while( pInode && memcmp(&fileId, &pInode->fileId, sizeof(fileId)) ){ 1336 1340 pInode = pInode->pNext; 1337 1341 } 1338 1342 if( pInode==0 ){ 1339 1343 pInode = sqlite3_malloc64( sizeof(*pInode) ); 1340 1344 if( pInode==0 ){ ................................................................................ 1746 1750 1747 1751 /* 1748 1752 ** Add the file descriptor used by file handle pFile to the corresponding 1749 1753 ** pUnused list. 1750 1754 */ 1751 1755 static void setPendingFd(unixFile *pFile){ 1752 1756 unixInodeInfo *pInode = pFile->pInode; 1753 - UnixUnusedFd *p = pFile->pUnused; 1757 + UnixUnusedFd *p = pFile->pPreallocatedUnused; 1754 1758 p->pNext = pInode->pUnused; 1755 1759 pInode->pUnused = p; 1756 1760 pFile->h = -1; 1757 - pFile->pUnused = 0; 1761 + pFile->pPreallocatedUnused = 0; 1762 + nUnusedFd++; 1758 1763 } 1759 1764 1760 1765 /* 1761 1766 ** Lower the locking level on file descriptor pFile to eFileLock. eFileLock 1762 1767 ** must be either NO_LOCK or SHARED_LOCK. 1763 1768 ** 1764 1769 ** If the locking level of the file descriptor is already at or below ................................................................................ 1975 1980 osUnlink(pFile->zPath); 1976 1981 sqlite3_free(*(char**)&pFile->zPath); 1977 1982 pFile->zPath = 0; 1978 1983 } 1979 1984 #endif 1980 1985 OSTRACE(("CLOSE %-3d\n", pFile->h)); 1981 1986 OpenCounter(-1); 1982 - sqlite3_free(pFile->pUnused); 1987 + sqlite3_free(pFile->pPreallocatedUnused); 1983 1988 memset(pFile, 0, sizeof(unixFile)); 1984 1989 return SQLITE_OK; 1985 1990 } 1986 1991 1987 1992 /* 1988 1993 ** Close a file. 1989 1994 */ ................................................................................ 3196 3201 assert( id ); 3197 3202 assert( offset>=0 ); 3198 3203 assert( amt>0 ); 3199 3204 3200 3205 /* If this is a database file (not a journal, master-journal or temp 3201 3206 ** file), the bytes in the locking range should never be read or written. */ 3202 3207 #if 0 3203 - assert( pFile->pUnused==0 3208 + assert( pFile->pPreallocatedUnused==0 3204 3209 || offset>=PENDING_BYTE+512 3205 3210 || offset+amt<=PENDING_BYTE 3206 3211 ); 3207 3212 #endif 3208 3213 3209 3214 #if SQLITE_MAX_MMAP_SIZE>0 3210 3215 /* Deal with as much of this read request as possible by transfering ................................................................................ 3309 3314 int wrote = 0; 3310 3315 assert( id ); 3311 3316 assert( amt>0 ); 3312 3317 3313 3318 /* If this is a database file (not a journal, master-journal or temp 3314 3319 ** file), the bytes in the locking range should never be read or written. */ 3315 3320 #if 0 3316 - assert( pFile->pUnused==0 3321 + assert( pFile->pPreallocatedUnused==0 3317 3322 || offset>=PENDING_BYTE+512 3318 3323 || offset+amt<=PENDING_BYTE 3319 3324 ); 3320 3325 #endif 3321 3326 3322 3327 #ifdef SQLITE_DEBUG 3323 3328 /* If we are doing a normal write to a database file (as opposed to ................................................................................ 5559 5564 /* Do not search for an unused file descriptor on vxworks. Not because 5560 5565 ** vxworks would not benefit from the change (it might, we're not sure), 5561 5566 ** but because no way to test it is currently available. It is better 5562 5567 ** not to risk breaking vxworks support for the sake of such an obscure 5563 5568 ** feature. */ 5564 5569 #if !OS_VXWORKS 5565 5570 struct stat sStat; /* Results of stat() call */ 5571 + 5572 + unixEnterMutex(); 5566 5573 5567 5574 /* A stat() call may fail for various reasons. If this happens, it is 5568 5575 ** almost certain that an open() call on the same path will also fail. 5569 5576 ** For this reason, if an error occurs in the stat() call here, it is 5570 5577 ** ignored and -1 is returned. The caller will try to open a new file 5571 5578 ** descriptor on the same path, fail, and return an error to SQLite. 5572 5579 ** 5573 5580 ** Even if a subsequent open() call does succeed, the consequences of 5574 5581 ** not searching for a reusable file descriptor are not dire. */ 5575 - if( 0==osStat(zPath, &sStat) ){ 5582 + if( nUnusedFd>0 && 0==osStat(zPath, &sStat) ){ 5576 5583 unixInodeInfo *pInode; 5577 5584 5578 - unixEnterMutex(); 5579 5585 pInode = inodeList; 5580 5586 while( pInode && (pInode->fileId.dev!=sStat.st_dev 5581 5587 || pInode->fileId.ino!=(u64)sStat.st_ino) ){ 5582 5588 pInode = pInode->pNext; 5583 5589 } 5584 5590 if( pInode ){ 5585 5591 UnixUnusedFd **pp; 5586 5592 for(pp=&pInode->pUnused; *pp && (*pp)->flags!=flags; pp=&((*pp)->pNext)); 5587 5593 pUnused = *pp; 5588 5594 if( pUnused ){ 5595 + nUnusedFd--; 5589 5596 *pp = pUnused->pNext; 5590 5597 } 5591 5598 } 5592 - unixLeaveMutex(); 5593 5599 } 5600 + unixLeaveMutex(); 5594 5601 #endif /* if !OS_VXWORKS */ 5595 5602 return pUnused; 5596 5603 } 5597 5604 5598 5605 /* 5599 5606 ** Find the mode, uid and gid of file zFile. 5600 5607 */ ................................................................................ 5807 5814 fd = pUnused->fd; 5808 5815 }else{ 5809 5816 pUnused = sqlite3_malloc64(sizeof(*pUnused)); 5810 5817 if( !pUnused ){ 5811 5818 return SQLITE_NOMEM_BKPT; 5812 5819 } 5813 5820 } 5814 - p->pUnused = pUnused; 5821 + p->pPreallocatedUnused = pUnused; 5815 5822 5816 5823 /* Database filenames are double-zero terminated if they are not 5817 5824 ** URIs with parameters. Hence, they can always be passed into 5818 5825 ** sqlite3_uri_parameter(). */ 5819 5826 assert( (flags & SQLITE_OPEN_URI) || zName[strlen(zName)+1]==0 ); 5820 5827 5821 5828 }else if( !zName ){ ................................................................................ 5844 5851 5845 5852 if( fd<0 ){ 5846 5853 mode_t openMode; /* Permissions to create file with */ 5847 5854 uid_t uid; /* Userid for the file */ 5848 5855 gid_t gid; /* Groupid for the file */ 5849 5856 rc = findCreateFileMode(zName, flags, &openMode, &uid, &gid); 5850 5857 if( rc!=SQLITE_OK ){ 5851 - assert( !p->pUnused ); 5858 + assert( !p->pPreallocatedUnused ); 5852 5859 assert( eType==SQLITE_OPEN_WAL || eType==SQLITE_OPEN_MAIN_JOURNAL ); 5853 5860 return rc; 5854 5861 } 5855 5862 fd = robust_open(zName, openFlags, openMode); 5856 5863 OSTRACE(("OPENX %-3d %s 0%o\n", fd, zName, openFlags)); 5857 5864 assert( !isExclusive || (openFlags & O_CREAT)!=0 ); 5858 5865 if( fd<0 && errno!=EISDIR && isReadWrite ){ ................................................................................ 5878 5885 } 5879 5886 } 5880 5887 assert( fd>=0 ); 5881 5888 if( pOutFlags ){ 5882 5889 *pOutFlags = flags; 5883 5890 } 5884 5891 5885 - if( p->pUnused ){ 5886 - p->pUnused->fd = fd; 5887 - p->pUnused->flags = flags; 5892 + if( p->pPreallocatedUnused ){ 5893 + p->pPreallocatedUnused->fd = fd; 5894 + p->pPreallocatedUnused->flags = flags; 5888 5895 } 5889 5896 5890 5897 if( isDelete ){ 5891 5898 #if OS_VXWORKS 5892 5899 zPath = zName; 5893 5900 #elif defined(SQLITE_UNLINK_AFTER_CLOSE) 5894 5901 zPath = sqlite3_mprintf("%s", zName); ................................................................................ 5961 5968 } 5962 5969 #endif 5963 5970 5964 5971 rc = fillInUnixFile(pVfs, fd, pFile, zPath, ctrlFlags); 5965 5972 5966 5973 open_finished: 5967 5974 if( rc!=SQLITE_OK ){ 5968 - sqlite3_free(p->pUnused); 5975 + sqlite3_free(p->pPreallocatedUnused); 5969 5976 } 5970 5977 return rc; 5971 5978 } 5972 5979 5973 5980 5974 5981 /* 5975 5982 ** Delete the file at zPath. If the dirSync argument is true, fsync() ................................................................................ 6702 6709 memset(pNew, 0, sizeof(unixFile)); 6703 6710 pNew->openFlags = openFlags; 6704 6711 memset(&dummyVfs, 0, sizeof(dummyVfs)); 6705 6712 dummyVfs.pAppData = (void*)&autolockIoFinder; 6706 6713 dummyVfs.zName = "dummy"; 6707 6714 pUnused->fd = fd; 6708 6715 pUnused->flags = openFlags; 6709 - pNew->pUnused = pUnused; 6716 + pNew->pPreallocatedUnused = pUnused; 6710 6717 6711 6718 rc = fillInUnixFile(&dummyVfs, fd, (sqlite3_file*)pNew, path, 0); 6712 6719 if( rc==SQLITE_OK ){ 6713 6720 *ppFile = pNew; 6714 6721 return SQLITE_OK; 6715 6722 } 6716 6723 end_create_proxy: