Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Internal enhancements to the native memory allocation wrapper. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
fcac33cc7a08686a894387d963ea3b90 |
User & Date: | mistachkin 2018-03-08 20:50:47.386 |
Context
2018-03-09
| ||
17:25 | Add more tests pursuant to ticket [baf42ee135]. check-in: d1b6742e1e user: mistachkin tags: trunk | |
2018-03-08
| ||
20:50 | Internal enhancements to the native memory allocation wrapper. check-in: fcac33cc7a user: mistachkin tags: trunk | |
18:13 | Prevent GetSchemaTable from throwing InvalidCastException. Fix for [baf42ee135]. check-in: c956230a3c user: mistachkin tags: trunk | |
Changes
Changes to System.Data.SQLite/SQLiteModule.cs.
︙ | ︙ | |||
3267 3268 3269 3270 3271 3272 3273 | /////////////////////////////////////////////////////////////////////// /// <summary> /// The total number of outstanding memory bytes allocated by this /// class using the SQLite core library. /// </summary> | | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313 3314 3315 3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354 3355 3356 3357 3358 3359 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 3399 3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410 3411 3412 3413 3414 3415 3416 3417 3418 3419 3420 3421 3422 3423 3424 3425 3426 3427 3428 3429 3430 3431 3432 3433 3434 | /////////////////////////////////////////////////////////////////////// /// <summary> /// The total number of outstanding memory bytes allocated by this /// class using the SQLite core library. /// </summary> private static ulong bytesAllocated; /////////////////////////////////////////////////////////////////////// /// <summary> /// The maximum number of outstanding memory bytes ever allocated by /// this class using the SQLite core library. /// </summary> private static ulong maximumBytesAllocated; #endif #endregion /////////////////////////////////////////////////////////////////////// #region Memory Tracking Helper Methods #if TRACK_MEMORY_BYTES /// <summary> /// Attempts to determine the size of the specified memory block. If /// the <see cref="Size64" /> method can be used, the returned value /// may be larger than <see cref="Int32.MaxValue" />. A message may /// be sent to the logging subsystem if an error is encountered. /// </summary> /// <param name="pMemory"> /// The native pointer to the memory block previously obtained from /// the <see cref="Allocate" />, <see cref="Allocate64" />, /// <see cref="AllocateUntracked" />, or /// <see cref="Allocate64Untracked" /> methods or directly from the /// SQLite core library. /// </param> /// <returns> /// The size of the specified memory block -OR- zero if the 32-bit /// signed value reported from the native API was less than zero. /// </returns> private static ulong GetBlockSize( IntPtr pMemory ) { ulong ulongSize = 0; if (CanUseSize64()) { ulongSize = Size64(pMemory); } else { int intSize = Size(pMemory); if (intSize > 0) { ulongSize = (ulong)intSize; } #if DEBUG else if (intSize < 0) { SQLiteLog.LogMessage(SQLiteErrorCode.Warning, HelperMethods.StringFormat(CultureInfo.CurrentCulture, "pointer {0} size {1} appears to be negative: {2}", pMemory, intSize, #if !PLATFORM_COMPACTFRAMEWORK Environment.StackTrace #else null #endif )); } #endif } return ulongSize; } /////////////////////////////////////////////////////////////////////// /// <summary> /// Adjusts the total number of (tracked) bytes that are currently /// considered to be allocated by this class. The total number is /// increased by the total size of the memory block pointed to by /// <paramref name="pMemory" />. If the new total number exceeds /// the previously seen maximum, the maximum will be reset. /// </summary> /// <param name="pMemory"> /// A native pointer to newly allocated memory. /// </param> private static void MemoryWasAllocated( IntPtr pMemory ) { if (pMemory != IntPtr.Zero) { ulong blockSize = GetBlockSize(pMemory); if (blockSize > 0) { lock (syncRoot) { bytesAllocated += blockSize; if (bytesAllocated > maximumBytesAllocated) maximumBytesAllocated = bytesAllocated; } } } } /////////////////////////////////////////////////////////////////////// /// <summary> /// Adjusts the total number of (tracked) bytes that are currently /// considered to be allocated by this class. The total number is /// decreased by the total size of the memory block pointed to by /// <paramref name="pMemory" />. /// </summary> /// <param name="pMemory"> /// A native pointer to allocated memory that is going to be freed. /// </param> private static void MemoryIsBeingFreed( IntPtr pMemory ) { if (pMemory != IntPtr.Zero) { ulong blockSize = GetBlockSize(pMemory); if (blockSize > 0) { lock (syncRoot) { bytesAllocated -= blockSize; } } } } #endif #endregion /////////////////////////////////////////////////////////////////////// #region Memory Version Helper Methods /// <summary> /// Determines if the native sqlite3_msize() API can be used, based on /// the available version of the SQLite core library. /// </summary> /// <returns> /// Non-zero if the native sqlite3_msize() API property is supported /// by the SQLite core library. /// </returns> private static bool CanUseSize64() { if (UnsafeNativeMethods.sqlite3_libversion_number() >= 3008007) return true; return false; } #endregion /////////////////////////////////////////////////////////////////////// #region Memory Allocation Helper Methods /// <summary> /// Allocates at least the specified number of bytes of native memory /// via the SQLite core library sqlite3_malloc() function and returns |
︙ | ︙ | |||
3302 3303 3304 3305 3306 3307 3308 | /// not be allocated. /// </returns> public static IntPtr Allocate(int size) { IntPtr pMemory = UnsafeNativeMethods.sqlite3_malloc(size); #if TRACK_MEMORY_BYTES | | > | | | < | < > | > > > > > > > > > > > > > | > > | < < > | < < > > | 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484 3485 3486 3487 | /// not be allocated. /// </returns> public static IntPtr Allocate(int size) { IntPtr pMemory = UnsafeNativeMethods.sqlite3_malloc(size); #if TRACK_MEMORY_BYTES MemoryWasAllocated(pMemory); #endif return pMemory; } /////////////////////////////////////////////////////////////////////// /// <summary> /// Allocates at least the specified number of bytes of native memory /// via the SQLite core library sqlite3_malloc64() function and returns /// the resulting native pointer. If the TRACK_MEMORY_BYTES option /// was enabled at compile-time, adjusts the number of bytes currently /// allocated by this class. /// </summary> /// <param name="size"> /// The number of bytes to allocate. /// </param> /// <returns> /// The native pointer that points to a block of memory of at least the /// specified size -OR- <see cref="IntPtr.Zero" /> if the memory could /// not be allocated. /// </returns> public static IntPtr Allocate64(ulong size) { IntPtr pMemory = UnsafeNativeMethods.sqlite3_malloc64(size); #if TRACK_MEMORY_BYTES MemoryWasAllocated(pMemory); #endif return pMemory; } /////////////////////////////////////////////////////////////////////// |
︙ | ︙ | |||
3347 3348 3349 3350 3351 3352 3353 3354 3355 | public static IntPtr AllocateUntracked(int size) { return UnsafeNativeMethods.sqlite3_malloc(size); } /////////////////////////////////////////////////////////////////////// /// <summary> /// Gets and returns the actual size of the specified memory block | > > > > > > > > > > > > > > > > > > > > > > > | > | | > | > | | 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525 3526 3527 3528 3529 3530 3531 3532 3533 3534 3535 3536 3537 3538 3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 | public static IntPtr AllocateUntracked(int size) { return UnsafeNativeMethods.sqlite3_malloc(size); } /////////////////////////////////////////////////////////////////////// /// <summary> /// Allocates at least the specified number of bytes of native memory /// via the SQLite core library sqlite3_malloc64() function and returns /// the resulting native pointer without adjusting the number of /// allocated bytes currently tracked by this class. This is useful /// when dealing with blocks of memory that will be freed directly by /// the SQLite core library. /// </summary> /// <param name="size"> /// The number of bytes to allocate. /// </param> /// <returns> /// The native pointer that points to a block of memory of at least the /// specified size -OR- <see cref="IntPtr.Zero" /> if the memory could /// not be allocated. /// </returns> public static IntPtr Allocate64Untracked(ulong size) { return UnsafeNativeMethods.sqlite3_malloc64(size); } /////////////////////////////////////////////////////////////////////// /// <summary> /// Gets and returns the actual size of the specified memory block /// that was previously obtained from the <see cref="Allocate" />, /// <see cref="Allocate64" />, <see cref="AllocateUntracked" />, or /// <see cref="Allocate64Untracked" /> methods or directly from the /// SQLite core library. /// </summary> /// <param name="pMemory"> /// The native pointer to the memory block previously obtained from /// the <see cref="Allocate" />, <see cref="Allocate64" />, /// <see cref="AllocateUntracked" />, or /// <see cref="Allocate64Untracked" /> methods or directly from the /// SQLite core library. /// </param> /// <returns> /// The actual size, in bytes, of the memory block specified via the /// native pointer. /// </returns> public static int Size(IntPtr pMemory) { |
︙ | ︙ | |||
3383 3384 3385 3386 3387 3388 3389 3390 3391 | #else return 0; #endif } /////////////////////////////////////////////////////////////////////// /// <summary> /// Frees a memory block previously obtained from the | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | | | | < < | < < < < < < < < < | 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 | #else return 0; #endif } /////////////////////////////////////////////////////////////////////// /// <summary> /// Gets and returns the actual size of the specified memory block /// that was previously obtained from the <see cref="Allocate" />, /// <see cref="Allocate64" />, <see cref="AllocateUntracked" />, or /// <see cref="Allocate64Untracked" /> methods or directly from the /// SQLite core library. /// </summary> /// <param name="pMemory"> /// The native pointer to the memory block previously obtained from /// the <see cref="Allocate" />, <see cref="Allocate64" />, /// <see cref="AllocateUntracked" />, or /// <see cref="Allocate64Untracked" /> methods or directly from the /// SQLite core library. /// </param> /// <returns> /// The actual size, in bytes, of the memory block specified via the /// native pointer. /// </returns> public static ulong Size64(IntPtr pMemory) { #if DEBUG SQLiteMarshal.CheckAlignment("Size64", pMemory, 0, IntPtr.Size); #endif return UnsafeNativeMethods.sqlite3_msize(pMemory); } /////////////////////////////////////////////////////////////////////// /// <summary> /// Frees a memory block previously obtained from the /// <see cref="Allocate" /> or <see cref="Allocate64" /> methods. If /// the TRACK_MEMORY_BYTES option was enabled at compile-time, adjusts /// the number of bytes currently allocated by this class. /// </summary> /// <param name="pMemory"> /// The native pointer to the memory block previously obtained from the /// <see cref="Allocate" /> or <see cref="Allocate64" /> methods. /// </param> public static void Free(IntPtr pMemory) { #if DEBUG SQLiteMarshal.CheckAlignment("Free", pMemory, 0, IntPtr.Size); #endif #if TRACK_MEMORY_BYTES MemoryIsBeingFreed(pMemory); #endif UnsafeNativeMethods.sqlite3_free(pMemory); } /////////////////////////////////////////////////////////////////////// |
︙ | ︙ | |||
4330 4331 4332 4333 4334 4335 4336 4337 4338 4339 4340 4341 4342 4343 | } #endregion /////////////////////////////////////////////////////////////////////// #region Private Methods #if DEBUG internal static void CheckAlignment( string type, IntPtr pointer, int offset, int size ) { | > > > > > > > > > > > > > > > > > > > > | 4531 4532 4533 4534 4535 4536 4537 4538 4539 4540 4541 4542 4543 4544 4545 4546 4547 4548 4549 4550 4551 4552 4553 4554 4555 4556 4557 4558 4559 4560 4561 4562 4563 4564 | } #endregion /////////////////////////////////////////////////////////////////////// #region Private Methods #if DEBUG /// <summary> /// Attempts to verify that the specified native pointer is properly /// aligned for the size of the data value. If that is not the case, /// a message will be sent to the logging subsystem. /// </summary> /// <param name="type"> /// The type of operation being performed by the caller. This value /// may be used within diagnostic messages. /// </param> /// <param name="pointer"> /// The <see cref="IntPtr" /> object instance representing the base /// memory location. /// </param> /// <param name="offset"> /// The integer offset from the base memory location where the data /// value to be read or written. /// </param> /// <param name="size"> /// The size, in bytes, of the data value. /// </param> internal static void CheckAlignment( string type, IntPtr pointer, int offset, int size ) { |
︙ | ︙ |
Changes to System.Data.SQLite/UnsafeNativeMethods.cs.
︙ | ︙ | |||
3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 | [DllImport(SQLITE_DLL)] #endif internal static extern IntPtr sqlite3_malloc(int n); #if !PLATFORM_COMPACTFRAMEWORK [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] #else [DllImport(SQLITE_DLL)] #endif internal static extern IntPtr sqlite3_realloc(IntPtr p, int n); #if !PLATFORM_COMPACTFRAMEWORK [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] #else [DllImport(SQLITE_DLL)] #endif internal static extern void sqlite3_free(IntPtr p); | > > > > > > > > > > > > > > > > > > > > > | 3360 3361 3362 3363 3364 3365 3366 3367 3368 3369 3370 3371 3372 3373 3374 3375 3376 3377 3378 3379 3380 3381 3382 3383 3384 3385 3386 3387 3388 3389 3390 3391 3392 3393 3394 3395 3396 3397 3398 | [DllImport(SQLITE_DLL)] #endif internal static extern IntPtr sqlite3_malloc(int n); #if !PLATFORM_COMPACTFRAMEWORK [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] #else [DllImport(SQLITE_DLL)] #endif internal static extern IntPtr sqlite3_malloc64(ulong n); #if !PLATFORM_COMPACTFRAMEWORK [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] #else [DllImport(SQLITE_DLL)] #endif internal static extern IntPtr sqlite3_realloc(IntPtr p, int n); #if !PLATFORM_COMPACTFRAMEWORK [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] #else [DllImport(SQLITE_DLL)] #endif internal static extern IntPtr sqlite3_realloc64(IntPtr p, ulong n); #if !PLATFORM_COMPACTFRAMEWORK [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] #else [DllImport(SQLITE_DLL)] #endif internal static extern ulong sqlite3_msize(IntPtr p); #if !PLATFORM_COMPACTFRAMEWORK [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] #else [DllImport(SQLITE_DLL)] #endif internal static extern void sqlite3_free(IntPtr p); |
︙ | ︙ | |||
4064 4065 4066 4067 4068 4069 4070 4071 4072 4073 4074 4075 4076 4077 | #if !PLATFORM_COMPACTFRAMEWORK [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] #else [DllImport(SQLITE_DLL)] #endif internal static extern IntPtr sqlite3_mprintf(IntPtr format, __arglist); #endregion // SQLite API calls that are provided by "well-known" extensions that may be statically // linked with the SQLite core native library currently in use. #region extension sqlite api calls #region virtual table #if INTEROP_VIRTUAL_TABLE #if !PLATFORM_COMPACTFRAMEWORK | > > | 4085 4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 | #if !PLATFORM_COMPACTFRAMEWORK [DllImport(SQLITE_DLL, CallingConvention = CallingConvention.Cdecl)] #else [DllImport(SQLITE_DLL)] #endif internal static extern IntPtr sqlite3_mprintf(IntPtr format, __arglist); #endregion /////////////////////////////////////////////////////////////////////////// // SQLite API calls that are provided by "well-known" extensions that may be statically // linked with the SQLite core native library currently in use. #region extension sqlite api calls #region virtual table #if INTEROP_VIRTUAL_TABLE #if !PLATFORM_COMPACTFRAMEWORK |
︙ | ︙ |