Showing preview only (510K chars total). Download the full file or copy to clipboard to get everything.
Repository: allisterb/jemalloc.NET
Branch: master
Commit: 73123d43a9fd
Files: 79
Total size: 484.1 KB
Directory structure:
gitextract_gm5xlq0e/
├── .gitattributes
├── .gitignore
├── .gitmodules
├── LICENSE
├── README.md
├── build.cmd
├── jemalloc.Api/
│ ├── Buffer.cs
│ ├── BufferHelpers.cs
│ ├── Extensions/
│ │ └── TypeExtensions.cs
│ ├── ExtentHooks.cs
│ ├── FixedBuffer.cs
│ ├── FixedBufferAllocation.cs
│ ├── FixedBufferEnumerator.cs
│ ├── GDI.cs
│ ├── GenericMath.cs
│ ├── HugeArray.cs
│ ├── HugeBuffer.cs
│ ├── HugeBufferEnumerator.cs
│ ├── IBufferAllocation.cs
│ ├── JemApi.cs
│ ├── JemPinnable.cs
│ ├── JemUtil.cs
│ ├── MemoryRef.cs
│ ├── NDArray.cs
│ ├── SafeArray.cs
│ ├── SafeBuffer.cs
│ ├── SafeBufferEnumerator.cs
│ ├── Utf8Buffer.cs
│ ├── jemalloc.Api.csproj
│ └── jemalloc.cs
├── jemalloc.Benchmarks/
│ ├── BenchmarkStatisticColumn.cs
│ ├── Benchmarks/
│ │ ├── FixedBufferVsManagedArray.cs
│ │ ├── HugeNativeVsManagedArray.cs
│ │ ├── MallocVsArray.cs
│ │ ├── SafeVsManagedArray.cs
│ │ └── Vector.cs
│ ├── Design.md
│ ├── JemBenchmark.cs
│ ├── JemBenchmarkAttribute.cs
│ ├── JemBenchmarkJobAttribute.cs
│ ├── JemBenchmarkParam.cs
│ ├── JemStatisticColumn.cs
│ ├── ProcessStatisticColumn.cs
│ ├── TestUDT.cs
│ └── jemalloc.Benchmarks.csproj
├── jemalloc.Bindings/
│ ├── App.config
│ ├── JemallocLibrary.cs
│ ├── Program.cs
│ ├── Properties/
│ │ └── AssemblyInfo.cs
│ ├── jemalloc-win-msvc.h
│ ├── jemalloc.Bindings.csproj
│ └── packages.config
├── jemalloc.Buffers/
│ ├── JemPinnable.cs
│ ├── NativeHelpers.cs
│ ├── NativeMemory.cs
│ └── jemalloc.Buffers.csproj
├── jemalloc.Cli/
│ ├── Options.cs
│ ├── Program.cs
│ ├── Properties/
│ │ └── PublishProfiles/
│ │ └── ReleaseProfile.pubxml
│ └── jemalloc.Cli.csproj
├── jemalloc.Examples/
│ ├── TestUDT.cs
│ └── jemalloc.Examples.csproj
├── jemalloc.NET.sln
├── jemalloc.StressTests/
│ ├── FixedBufferStressTests.cs
│ └── jemalloc.StressTests.csproj
├── jemalloc.Tests/
│ ├── BufferTests.cs
│ ├── FixedBufferTests.cs
│ ├── HugeArrayTests.cs
│ ├── MallCtlTests.cs
│ ├── MallocConfTests.cs
│ ├── MallocMessageTests.cs
│ ├── MallocTests.cs
│ ├── SafeArrayTests.cs
│ ├── UDTTests.cs
│ ├── Utf8BufferTests.cs
│ ├── VectorTests.cs
│ ├── jemalloc.Tests.csproj
│ └── jemallocTest.cs
└── jembench.cmd
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitattributes
================================================
###############################################################################
# Set default behavior to automatically normalize line endings.
###############################################################################
* text=auto
###############################################################################
# Set default behavior for command prompt diff.
#
# This is need for earlier builds of msysgit that does not have it on by
# default for csharp files.
# Note: This is only used by command line
###############################################################################
#*.cs diff=csharp
###############################################################################
# Set the merge driver for project and solution files
#
# Merging from the command prompt will add diff markers to the files if there
# are conflicts (Merging from VS is not affected by the settings below, in VS
# the diff markers are never inserted). Diff markers may cause the following
# file extensions to fail to load in VS. An alternative would be to treat
# these files as binary and thus will always conflict and require user
# intervention with every merge. To do so, just uncomment the entries below
###############################################################################
#*.sln merge=binary
#*.csproj merge=binary
#*.vbproj merge=binary
#*.vcxproj merge=binary
#*.vcproj merge=binary
#*.dbproj merge=binary
#*.fsproj merge=binary
#*.lsproj merge=binary
#*.wixproj merge=binary
#*.modelproj merge=binary
#*.sqlproj merge=binary
#*.wwaproj merge=binary
###############################################################################
# behavior for image files
#
# image files are treated as binary by default.
###############################################################################
#*.jpg binary
#*.png binary
#*.gif binary
###############################################################################
# diff behavior for common document formats
#
# Convert binary document formats to text before diffing them. This feature
# is only available from the command line. Turn it on by uncommenting the
# entries below.
###############################################################################
#*.doc diff=astextplain
#*.DOC diff=astextplain
#*.docx diff=astextplain
#*.DOCX diff=astextplain
#*.dot diff=astextplain
#*.DOT diff=astextplain
#*.pdf diff=astextplain
#*.PDF diff=astextplain
#*.rtf diff=astextplain
#*.RTF diff=astextplain
================================================
FILE: .gitignore
================================================
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
# Visual Studio 2015 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# DNX
project.lock.json
project.fragment.lock.json
artifacts/
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding add-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# TODO: Comment the next line if you want to checkin your web deploy settings
# but database connection strings (with potential passwords) will be unencrypted
#*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/packages/repositories.config
# NuGet v3's project.json files produces more ignoreable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
node_modules/
orleans.codegen.cs
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
*.mdf
*.ldf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# JetBrains Rider
.idea/
*.sln.iml
# CodeRush
.cr/
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
/BenchmarkDotNet.Artifacts/results
/jemalloc.Cli/BenchmarkDotNet.Artifacts/results
/jemalloc.Cli/Properties/launchSettings.json
/*.ppm
================================================
FILE: .gitmodules
================================================
[submodule "jemalloc"]
path = jemalloc
url = https://github.com/allisterb/jemalloc.git
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2017 Allister Beharry
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: README.md
================================================
# jemalloc.NET: A native memory manager for .NET

Get the latest 0.2.x release from the [releases](https://github.com/allisterb/jemalloc.NET/releases) page.
jemalloc.NET is a .NET API over the [jemalloc](http://jemalloc.net/) native memory allocator and provides .NET applications with efficient data structures backed by native memory for large scale in-memory computation scenarios. jemalloc is "a general purpose malloc(3) implementation that emphasizes fragmentation avoidance and scalable concurrency support" that is [widely used](https://github.com/jemalloc/jemalloc/wiki/Background#adoption) in the industry, particularly in applications that must [scale and utilize](http://highscalability.com/blog/2015/3/17/in-memory-computing-at-aerospike-scale-when-to-choose-and-ho.html) large amounts of memory. In addition to its fragmentation and concurrency optimizations, jemalloc provides an array of developer options for debugging, monitoring and tuning allocations that makes it a great choice for use in developing memory-intensive applications.
The jemalloc.NET project provides:
* A low-level .NET API over the native jemalloc API functions like je_malloc, je_calloc, je_free, je_mallctl...
* A safety-focused high-level .NET API providing data structures like arrays backed by native memory allocated using jemalloc together with management features like reference counting and acceleration features like SIMD vectorized operations via the `Vector<T>` .NET type.
* A benchmark CLI program: `jembench` which uses the excellent [BenchmarkDotNet](http://benchmarkdotnet.org/index.htm) library for easy and accurate benchmarking operations on native data structures vs managed objects using different parameters.
The high-level .NET API makes use of newly introduced C# and .NET features and classes like ref returns, `Span<T>`, `Vector<T>`, and `Unsafe<T>` from the `System.Runtime.CompilerServices.Unsafe` libraries, for working effectively with pointers to managed and unmanaged memory.
Data structures provided by the high-level API are more efficient than managed .NET arrays and objects at the scale of millions of elements, and memory allocation is much more resistant to fragmentation, while still providing necessary safety features like array bounds checking. Large .NET arrays must be allocated on the Large Object Heap and are not relocatable which leads to fragmentation and lower performance. In a [benchmark](https://github.com/allisterb/jemalloc.NET/blob/5d00a6969faf828261ce8f28492b0df2e7297dad/jemalloc.Benchmarks/Benchmarks/MallocVsArray.cs#L136) specifically designed to fragment managed and unmanaged memory using arrays of `Int32`, jemalloc.NET performs a order of magnitude better that the .NET managed heap allocator at the cost of higher memory utilization:
``` ini
BenchmarkDotNet=v0.10.11, OS=Windows 10 Redstone 2 [1703, Creators Update] (10.0.15063.726)
Processor=Intel Core i7-6700HQ CPU 2.60GHz (Skylake), ProcessorCount=8
Frequency=2531251 Hz, Resolution=395.0616 ns, Timer=TSC
.NET Core SDK=2.1.2
[Host] : .NET Core 2.0.3 (Framework 4.6.25815.02), 64bit RyuJIT
Job=JemBenchmark Jit=RyuJit Platform=X64
Runtime=Core AllowVeryLargeObjects=True Toolchain=InProcessToolchain
RunStrategy=ColdStart
```
| Method | Parameter | Mean | Error | StdDev | PrivateMemory | Scaled | ScaledSD | Gen 0 | Gen 1 | Gen 2 | Allocated |
|--------------------------------------------------------------------------------------------- |---------- |----------:|----------:|----------:|--------------:|-------:|---------:|------------:|------------:|------------:|------------:|
| 'Run an allocation pattern that won't fragment the Large Object Heap.' | 100 | 763.74 ms | 7.536 ms | 7.049 ms | 42.1 MB | 1.00 | 0.00 | 101000.0000 | 101000.0000 | 101000.0000 | 45436.08 MB |
| 'Run an allocation pattern that fragments the Large Object Heap.' | 100 | 786.95 ms | 15.568 ms | 19.689 ms | 76.0 MB | 1.03 | 0.03 | 101000.0000 | 101000.0000 | 101000.0000 | 45436.09 MB |
| 'Run an allocation pattern that fragments the Large Object Heap with regular GC compaction.' | 100 | 790.30 ms | 15.392 ms | 19.466 ms | 75.9 MB | 1.03 | 0.03 | 111000.0000 | 111000.0000 | 111000.0000 | 45436.08 MB |
| 'Run an allocation pattern that won't fragment the unmanaged heap.' | 100 | 59.63 ms | 2.205 ms | 6.502 ms | 52.6 MB | 0.08 | 0.01 | 1000.0000 | 1000.0000 | 1000.0000 | 1.97 MB |
| 'Run an allocation pattern that fragments the unmanaged heap.' | 100 | 69.48 ms | 1.376 ms | 2.810 ms | 90.7 MB | 0.09 | 0.00 | 1000.0000 | 1000.0000 | 1000.0000 | 2.59 MB |
You can run this benchmark with the jembench command: `jembench malloc --fragment 100 -u -b --cold-start`
In the following `jembench` benchmark, simply filling an array is more or less the same across different kinds of memory and scales linearly depending on the size of the array, but *allocating* and filling a `UInt64[]` managed array of size 10000000 and 100000000 is more than 2x slower than using an equivalent native array provided by jemalloc.NET:
``` ini
BenchmarkDotNet=v0.10.11, OS=Windows 10 Redstone 2 [1703, Creators Update] (10.0.15063.726)
Processor=Intel Core i7-6700HQ CPU 2.60GHz (Skylake), ProcessorCount=8
Frequency=2531251 Hz, Resolution=395.0616 ns, Timer=TSC
.NET Core SDK=2.1.2
[Host] : .NET Core 2.0.3 (Framework 4.6.25815.02), 64bit RyuJIT
Job=JemBenchmark Jit=RyuJit Platform=X64
Runtime=Core AllowVeryLargeObjects=True Toolchain=InProcessToolchain
RunStrategy=Throughput
```
| Method | Parameter | Mean | Error | StdDev | Median | Gen 0 | Gen 1 | Gen 2 | Allocated |
|-------------------------------------------------------------------------------- |---------- |-----------:|----------:|----------:|-----------:|---------:|---------:|---------:|------------:|
| **'Fill a managed array with a single value.'** | **10000000** | **9.059 ms** | **0.1745 ms** | **0.4777 ms** | **8.913 ms** | **-** | **-** | **-** | **208 B** |
| 'Fill a SafeArray on the system unmanaged heap with a single value.' | 10000000 | 8.715 ms | 0.1682 ms | 0.2466 ms | 8.623 ms | - | - | - | 208 B |
| 'Create and Fill a managed array with a single value.' | 10000000 | 32.867 ms | 0.9156 ms | 1.3420 ms | 32.175 ms | 142.8571 | 142.8571 | 142.8571 | 80000769 B |
| 'Create and Fill a SafeArray on the system unmanaged heap with a single value.' | 10000000 | 13.809 ms | 0.2679 ms | 0.2506 ms | 13.727 ms | - | - | - | 192 B |
| **'Fill a managed array with a single value.'** | **100000000** | **90.326 ms** | **1.7718 ms** | **2.4253 ms** | **89.468 ms** | **-** | **-** | **-** | **208 B** |
| 'Fill a SafeArray on the system unmanaged heap with a single value.' | 100000000 | 88.377 ms | 0.9775 ms | 0.8665 ms | 88.505 ms | - | - | - | 208 B |
| 'Create and Fill a managed array with a single value.' | 100000000 | 310.880 ms | 5.9732 ms | 8.1762 ms | 306.952 ms | 125.0000 | 125.0000 | 125.0000 | 800000624 B |
| 'Create and Fill a SafeArray on the system unmanaged heap with a single value.' | 100000000 | 137.288 ms | 0.9710 ms | 0.9083 ms | 137.111 ms | - | - | - | 192 B |
You can run this benchmark with the command `jembench array --fill 10000000 100000000 -l -u`. In this case we see that using the managed array of size 10 million elements allocated 800 MB on the managed heap while using the native array did not cause any allocations on the managed heap for the array data. Avoiding the managed heap for very large but simple data structures like arrays is a key optimizarion for apps that do large-scale in-memory computation.
Managed .NET arays are also limited to `Int32` indexing and a maximum size of about 2.15 billion elements. jemalloc.NET provides huge arrays through the `HugeArray<T>` class which allows you to access all available memory as a flat contiguous buffer using array semantics. In the next benchmark `jembench hugearray --fill -i 4200000000`:
``` ini
BenchmarkDotNet=v0.10.11, OS=Windows 10 Redstone 2 [1703, Creators Update] (10.0.15063.726)
Processor=Intel Core i7-6700HQ CPU 2.60GHz (Skylake), ProcessorCount=8
Frequency=2531251 Hz, Resolution=395.0616 ns, Timer=TSC
.NET Core SDK=2.1.2
[Host] : .NET Core 2.0.3 (Framework 4.6.25815.02), 64bit RyuJIT
Job=JemBenchmark Jit=RyuJit Platform=X64
Runtime=Core AllowVeryLargeObjects=True Toolchain=InProcessToolchain
RunStrategy=ColdStart TargetCount=7 WarmupCount=-1
```
| Method | Parameter | Mean | Error | StdDev | Allocated |
|------------------------------------------------------------------------------- |----------- |--------:|---------:|---------:|-------------:|
| 'Fill a managed array with the maximum size [2146435071] with a single value.' | 4200000000 | 3.177 s | 0.1390 s | 0.0617 s | 8585740456 B |
| 'Fill a HugeArray on the system unmanaged heap with a single value.' | 4200000000 | 4.029 s | 3.2233 s | 1.4312 s | 0 B |
an `Int32[]` of maximum size can be allocated and filled in 3.2s. This array consumes 8.6GB on the managed heap. But a jemalloc.NET `HugeArray<Int32>` of nearly double the size at 4.2 billion elements can be allocated in only 4 s and again consumes no memory on the managed heap. The only limit on the size of a `HugeArray<T>` is the available system memory.
Perhaps the killer feature of the [recently introduced](https://blogs.msdn.microsoft.com/dotnet/2017/11/15/welcome-to-c-7-2-and-span/) `Span<T>` class in .NET is its ability to efficiently zero-copy reinterpret numeric data structures (`Int32, Int64` and their siblings) into other structures like the `Vector<T>` SIMD-enabled data types introduced in 2016. `Vector<T>` types are special in that the .NET RyuJIT compiler can compile operations on Vectors to use SIMD instructions like SSE, SSE2, and AVX for parallelizing operations on data on a single CPU core.
Using the SIMD-enabled `SafeBuffer<T>.VectorMultiply(n)` method provided by the jemalloc.NET API yields a more than 12x speedup for a simple in-place multiplication of a `UInt64[]` array of 10 million elements, compared to the unoptimized linear approach, allowing the operation to complete in 60 ms:
``` ini
BenchmarkDotNet=v0.10.11, OS=Windows 10 Redstone 2 [1703, Creators Update] (10.0.15063.726)
Processor=Intel Core i7-6700HQ CPU 2.60GHz (Skylake), ProcessorCount=8
Frequency=2531251 Hz, Resolution=395.0616 ns, Timer=TSC
.NET Core SDK=2.1.2
[Host] : .NET Core 2.0.3 (Framework 4.6.25815.02), 64bit RyuJIT
Job=JemBenchmark Jit=RyuJit Platform=X64
Runtime=Core AllowVeryLargeObjects=True Toolchain=InProcessToolchain
RunStrategy=Throughput
```
| Method | Parameter | Mean | Error | StdDev | Gen 0 | Gen 1 | Allocated |
|-------------------------------------------------------------------- |---------- |----------:|----------:|---------:|------------:|--------:|------------:|
| 'Multiply all values of a managed array with a single value.' | 10000000 | 761.10 ms | 10.367 ms | 9.190 ms | 254250.0000 | 62.5000 | 800000304 B |
| 'Vector multiply all values of a native array with a single value.' | 10000000 | 59.23 ms | 1.170 ms | 1.149 ms | - | - | 360 B |
For huge arrays of `UInt16[]` we see similar speedups:
``` ini
BenchmarkDotNet=v0.10.11, OS=Windows 10 Redstone 2 [1703, Creators Update] (10.0.15063.726)
Processor=Intel Core i7-6700HQ CPU 2.60GHz (Skylake), ProcessorCount=8
Frequency=2531251 Hz, Resolution=395.0616 ns, Timer=TSC
.NET Core SDK=2.1.2
[Host] : .NET Core 2.0.3 (Framework 4.6.25815.02), 64bit RyuJIT
Job=JemBenchmark Jit=RyuJit Platform=X64
Runtime=Core AllowVeryLargeObjects=True Toolchain=InProcessToolchain
RunStrategy=ColdStart TargetCount=1
```
| Method | Parameter | Mean | Error | Gen 0 | Gen 1 | Allocated |
|------------------------------------------------------------------------------------------------- |----------- |--------:|------:|--------------:|----------:|--------------:|
| 'Multiply all values of a managed array with the maximum size [2146435071] with a single value.' | 4096000000 | 34.25 s | NA | 16375000.0000 | 3000.0000 | 51514441704 B |
| 'Vector multiply all values of a native array with a single value.' | 4096000000 | 12.06 s | NA | - | - | 0 B |
For a huge array with 4.1 billion `UInt16` values it takes 12 seconds to do a SIMD-enabled multiplication operation on all the elements of the array. This is still 3x the performance of doing the same non-vectorized operation on a managed array of half the size.
Inside a .NET application, jemalloc.NET native arrays and data structures can be straightforwardly accessed by native libraries without the need to make additional copies or allocations. The goal of the jemalloc.NET project is to make accessible to .NET the kind of big-data in-memory numeric, scientific and other computing that typically would require coding in a low-level language like C/C++ or assembly.
## How it works
Memory allocations are made using the jemalloc C functions like `je_malloc`, `je_calloc` etc, and returned as `IntPtr` pointers. Memory alignment is handled by jemalloc and memory allocations (called extents) are aligned to a multiple of the jemalloc page size e.g 4K. Inside extents, elements are aligned according to the .NET struct alignment specified using the `StructLayout` and other attributes. In the future the ability to manually align structures inside an extend and jemalloc's ability to manually align each extent (e.g using the `je_posix_memalign` function) may be exposed to alleviate potential [performance problems](http://adrianchadd.blogspot.se/2015/03/cache-line-aliasing-2-or-what-happens.html) with the default jemalloc page alignment.
Each allocation pointer is tracked in a thread-safe allocations ledger together with a reference count. Each valid Jem.NET data structure has a pointer in the allocations ledger. There are other allocation ledgers that track details of different data structures like `FixedBufferAllocation`. When a pointer to an extent is released by a data stucture it is removed from all allocation ledgers. During the free operation the memory extent is filled with junk values by jemalloc as a safety feature however this feature and many other aspects of jemalloc can be turned off or on by the user.
Any attempt to read or write data structure memory locations is guarded by checking that the data structure owns a valid pointer to the memory location. Since there can't be two pointers allocated with the same address at the same time, pointers act as a unique Id for tracking the active memory extents. Data structures are provided with reference counting methods like `Acquire()` and `Release()` to manage their lifetimes. Attempts to free or dispose of a data structure with a non-zero reference count will throw an exception. Unlike the stack-only `Span<T>` you are allowed to use class fields and properties to hold Jem.NET data structures like `FixedBuffer<T>` because `FixedBuffer<T>` guards every access to memory by first checking if the memory extent it is assigned is still valid. However you must take responsibility for using the reference counting features correctly i.e when sharing data structures between methods and threads you should always call `FixedBuffer<T>`.Acquire() to prevent a nethod from accidentally releasing the buffer's memory when it is in use.
In data structures like `FixedBuffer<T>` the primitive .NET types are always correctly aligned for SIMD vectorized operations and such operations like `FixedBuffer<T>.VectorMultiply()` can be significatnly faster than the non-optimized variants. E.g. an in-place multiplication of a `FixedBuffer<Uint16>` is many times faster than the same operation on a .NET `Uint16[]`:
``` ini
BenchmarkDotNet=v0.10.11, OS=Windows 10 Redstone 2 [1703, Creators Update] (10.0.15063.726)
Processor=Intel Core i7-6700HQ CPU 2.60GHz (Skylake), ProcessorCount=8
Frequency=2531251 Hz, Resolution=395.0616 ns, Timer=TSC
.NET Core SDK=2.1.2
[Host] : .NET Core 2.0.3 (Framework 4.6.25815.02), 64bit RyuJIT
Job=JemBenchmark Jit=RyuJit Platform=X64
Runtime=Core AllowVeryLargeObjects=True Toolchain=InProcessToolchain
RunStrategy=Throughput
```
| Method | Parameter | Mean | Error | StdDev | Gen 0 | Gen 1 | Allocated |
|-------------------------------------------------------------------- |---------- |----------:|----------:|----------:|------------:|-------:|------------:|
| 'Multiply all values of a managed array with a single value.' | 10000000 | 606.33 ms | 4.1602 ms | 3.4740 ms | 228875.0000 | 4.1667 | 703125.3 KB |
| 'Vector multiply all values of a native array with a single value.' | 10000000 | 36.40 ms | 0.5256 ms | 0.4659 ms | - | - | 1.32 KB |
Pointers to data structure memory extents can be passed directly to unmanaged functions and libraries without the need for marshalling or more allocations. This is important when you want to build high-performance apps that use libraries written in C or assembly that process large amounts of in-memory data.
## Installation
### Requirements
Currently only runs on 64bit Windows; support for Linux 64bit and other 64bit platforms supported by .NET Core will be added
soon.
#### Windows
* The latest [.NET Core 2.0 x64 runtime](https://www.microsoft.com/net/download/thank-you/dotnet-runtime-2.0.3-windows-x64-installer)
* The latest version of the [Microsoft Visual C++ Redistributable for Visual Studio 2017](https://go.microsoft.com/fwlink/?LinkId=746572)
### Steps
Grab the latest release from the [releases](https://github.com/allisterb/jemalloc.NET/releases) page and unzip to a folder. Type `jembench` to run the benchmark CLI program and you should see the program version and options printed. NuGet packagees can be found in x64\Release. The API library assembly files themselves are in x64\Release\netstandard2.0
Note that if using jemalloc.NET in your own projects you must put the native jemallocd.dll library somewhere where it can be located by the .NET runtime. You can create a post-build step to copy it to the output folder of your project or put it somewhere on your %PATH%.
## Usage
### High-level API
Currently there are 4 implemented native memory data structures:
### 1. `FixedBuffer<T>`
`FixedBuffer<T>` is a fixed-length array of data backed by memory on the unmanaged heap, that is implemented as .NET `struct`. The underlying data type of a `FixedBuffer<T>` must be a [primitive](https://msdn.microsoft.com/en-us/library/system.type.isprimitive.aspx) type: Boolean, Byte, SByte, Int16, UInt16, Int32, UInt32, Int64, UInt64, IntPtr, UIntPtr, Char, Double, or Single.
```
FixedBuffer<Int64> buffer = new FixedBuffer<Int64>(1000000); // Create an array of 1 million Int64 integers.
buffer.Fill(100);
long a = buffer[10]; //copy on read
ref long b = ref buffer[10]; // no copy...b is an alias to the memory location of buffer[10]
```
Primitives types have a maximum width of 64bits and (assuming correct memory alignment) can be read and updated atomically on machines with a 64bit word-size. This eliminates the possibility of 'struct tearing', or struct fields being read or written to inconsistently by multiple concurrent operations, because reads and writes to `FixedBuffer<T>` elements are only done directly to the underlying memory location for the data element.
All properties and fields of `FixedBuffer<T>` are readonly with only the index operator `[]` returing a `ref T` to the underlying data element. To use copy-on-read semantics simply create and assign variables to elements in the array. Use `ref` variables to get an alias to the memory location itself:
FixedBuffer<int> b = ...;
int num = b[15];
num = 6; // b[15] is still 6
ref int r = ref b[15]; //get an alias to b[15]
r = 23; // b[15] is now
Although `FixedBuffer<T>` is a .NET value type, only the metadata about the data structure is copied from one variable assignment to another. The actual data of a `FixedBuffer<T>` resides at a single memory location only. Each data access to a `<T>` element in a `FixedBuffer<T>` from all copies of a `FixedBuffer<T>` will read and write the same memory and makes the same guard checks against the same pointer in the allocations ledger. When the pointer used by a FixedBuffer<T> is released then every copy of a `FixedBuffer<T>` automatically becomes invalid. e.g:
```
FixedBuffer<int> array = new FixedBuffer<int>(100);
array[16] = 1;
FixedBuffer<int> copy = array;
int a = copy[16]; // a is 16;
copy[5] = 99;
int b = array[5]; // b is 99
copy.Free(); Invalidate the buffer from the copy
int c = array[16]; //InvalidOperationException thrown here
```
You can create user-defined structures that contain `FixedBuffer<T>` e.g
public struct Employee : IEquatable<Employee>
{
...
public DateTime? DOB { get; set; }
public decimal Balance { get; set; }
public FixedBuffer<float> BonusPayments { get; set; }
public FixedBuffer<byte> Photo { get; set; } //8
}
The `FixedUtf8String` [type](https://github.com/allisterb/jemalloc.NET/blob/master/jemalloc.Api/FixedUtf8String.cs) is another `struct` that uses a `FixedBuffer<byte>` for storage of string data.
```
public readonly struct FixedUtf8String : IEquatable<FixedUtf8String>, IRetainable, IDisposable
{
...
#region Fields
private readonly FixedBuffer<byte> buffer;
private const int StringNotFound = -1;
...
```
Each `FixedBuffer<T>` has a constructor from `T[]` which copies the data from the managed array to the unmanaged buffer allocated.
```
public static TestUDT MakeTestRecord(Random rng)
{
Guid _id = Guid.NewGuid();
string _ids = _id.ToString("N");
byte[] photo = new byte[4096];
rng.NextBytes(photo);
return new TestUDT()
{
ID = _id,
FirstName = new FixedUtf8String("Gavial-" + _id.ToString("D").Substring(0, 4)),
LastName = new FixedUtf8String("Buxarinovich-" + _id.ToString("D").Substring(0, 4)),
DOB = _ids.StartsWith("7") ? (DateTime?)null : DateTime.UtcNow,
Balance = 2131m,
Photo = new FixedBuffer<byte>(photo)
};
}
```
Arrays of these kinds of user-defined structures can also be stored in native memory using the `SafeBuffer<T>` class.
### 2. `SafeBuffer<T>`
`SafeBuffer<T>` is a fixed-length array of data backed by memory on the unmanaged heap that inherits from the .NET `SafeHandle` class and is implemented as .NET `class` i.e a reference type. `SafeBuffer<T>` is an abstract class that can be used as the base to create data-structures like arrays or trees that are backed by unmanaged memory. The implemented `SafeArray<T>` class is the simplest concrete class that derives from `SafeBuffer`. `SafeArray<T>` can contain both primitive types and user-defined structures e.g:
```
public struct Employee : IEquatable<Employee>
{
public Guid ID { get; set; }
public FixedUtf8String FirstName { get; set; }
public FixedUtf8String LastName { get; set; }
public DateTime? DOB { get; set; }
public decimal Salary { get; set; }
public FixedBuffer<float> Bonuses { get; set; }
public FixedBuffer<byte> Photo { get; set; }
}
...
public SafeArray<Employee> employees = new SafeArray<Employee>(100);
```
The only restrictions on the type `T` of a `SafeBuffer<T>` is that it must be a struct and it must implement `IEquatable<T>`
### 3. `FixedUtf8Buffer`
`FixedUtf8Buffer`is a fixed-length immutable string type using UTF-8 encoding that is backed by memory on the unmanaged heap and is implemented as a .NET `struct` You can create user-defined structures that contain a `FixedUtf8Buffer` or create a `SafeBuffer<FixedUtf8Buffer>` for representing arrays of stringd. Some commmon string operations are implemented like `IndexOf()` and `Substring()` and there is a constructor taking a .NET `String`.
### 4. `HugeBuffer<T>`
`HugeBuffer<T>` is similar to `SafeBuffer<T>` but with the ability to store and index up to `Int64.MaxValue` array elements. `HugeBuffer<T>` lets you treat all available memory as a linear contiguous buffer.
### Tuning jemalloc
The jemalloc allocator contains many parameters that can be adjusted to suit the workload and allocation patterns of the application.
`Jem.Init(string conf)`
`Jem.SetMallCtlInt32(int value)`
### jembench CLI
Examples:
* `jembench hugearray -l -u --math --cold-start -t 3 4096000000` Benchmark math operations on `HugeArray<UInt64>` arrays of size 4096000000 without benchmark warmup and only using 3 iterations of the target methods. Benchmarks on huge arrays can be lengthy so you should carefully choose the benchmark parameters affecting how long you want the benchmark to run,
## Building from source
Currently build instuctions are only provided for Visual Studio 2017 on Windows but instructions for building on Linux will also be provided. jemalloc.NET is a 64-bit library only.
### Requirements
[Visual Studio 2017 15.5](https://www.visualstudio.com/en-us/news/releasenotes/vs2017-relnotes#15.5.1) with at least the following components:
* C# 7.2 compiler
* .NET Core 2.x SDK x64
* MSVC 2017 compiler toolset v141 or higher
* Windows 10 SDK for Desktop C++ version 10.0.10.15603 or higher. Note that if you only have higher versions installed you will need to retarget the jemalloc MSVC project to your SDK version from Visual Studio.
Per the instructions for building the native jemalloc library for Windows, you will also need Cygwin (32- or 64-bit )with the following packages:
* autoconf
* autogen
* gcc
* gawk
* grep
* sed
Cygwin tools aren't actually used for compiling jemalloc but for generating the header files. jemalloc on Windows is built using MSVC.
### Steps
0. You must add the [.NET Core](https://dotnet.myget.org/gallery/dotnet-core) NuGet [feed](https://dotnet.myget.org/F/dotnet-core/api/v3/index.json) on MyGet and also the [CoreFxLab](https://dotnet.myget.org/gallery/dotnet-corefxlab) [feed](https://dotnet.myget.org/F/dotnet-core/api/v3/index.json) to your NuGet package sources. You can do this in Visual Studio 2017 from Tools->Options->NuGet Package Manager menu item.
1. Clone the project: `git clone https://github.com/alllisterb/jemalloc.NET` and init the submodules: `git submodule update --init --recursive`
2. Open a x64 Native Tools Command Prompt for VS 2017 and temporarily add `Cygwin\bin` to the PATH e.g `set PATH=%PATH%;C:\cygwin\bin`. Switch to the `jemalloc` subdirectory in your jemalloc.NET solution dir and run `sh -c "CC=cl ./autogen.sh"`. This will generate some files in the `jemalloc` subdirectory and only needs to be done once.
4. From a Visual Studio 2017 Developer Command prompt run `build.cmd`. Alternatively you can load the solution in Visual Studio and using the "Benchmark" solution configuration build the entire solution.
5. The solution should build without errors.
6. Run `jembench` from the solution folder to see the project version and help.
================================================
FILE: build.cmd
================================================
@echo off
@setlocal
set ERROR_CODE=0
dotnet restore jemalloc.NET.sln
if not %ERRORLEVEL%==0 (
echo Error restoring NuGet packages for jemalloc.NET.sln.
set ERROR_CODE=1
goto End
)
if [%1]==[] (
msbuild jemalloc.NET.sln /p:Configuration=Benchmark /p:Platform=x64
) else (
msbuild jemalloc.NET.sln /p:Configuration=Benchmark /p:Platform=x64;%*
)
if not %ERRORLEVEL%==0 (
echo Error building jemalloc.NET.sln.
set ERROR_CODE=2
goto End
)
:End
@endlocal
exit /B %ERROR_CODE%
================================================
FILE: jemalloc.Api/Buffer.cs
================================================
using System;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Threading;
namespace jemalloc
{
public ref struct Buffer<T> where T : struct
{
public Buffer(int length)
{
_Ptr = IntPtr.Zero;
_Length = 0;
_SizeInBytes = 0;
_Timestamp = 0;
_Span = new Span<T>();
unsafe
{
_VoidPointer = (void*)_Ptr;
}
Allocate(length);
}
#region Properties
public bool IsInvalid
{
get
{
return _Ptr == IntPtr.Zero;
}
}
public int Length
{
get
{
if (IsInvalid)
{
return 0;
}
else
{
return _Length;
}
}
}
public ulong Size
{
get
{
if (IsInvalid)
{
return 0;
}
else
{
return _SizeInBytes;
}
}
}
public IntPtr Ptr
{
get
{
return _Ptr;
}
}
public Span<T> Span
{
get
{
if (IsInvalid)
{
throw new InvalidOperationException("The buffer is invalid.");
}
else
{
return _Span;
}
}
}
#endregion
#region Methods
private unsafe bool Allocate(int length)
{
_Ptr = Jem.Calloc((ulong) length, ElementSizeInBytes);
if (_Ptr != IntPtr.Zero)
{
_Length = length;
_SizeInBytes = (ulong)_Length * ElementSizeInBytes;
_Timestamp = DateTime.Now.Ticks;
_VoidPointer = _Ptr.ToPointer();
_Span = new Span<T>(_VoidPointer, _Length);
return true;
}
else return false;
}
public void Release()
{
if (IsInvalid)
{
return;
}
else if (Interlocked.Exchange(ref _Ptr, IntPtr.Zero) != IntPtr.Zero)
{
Jem.Free(_Ptr);
}
}
public void Fill(T value)
{
if (IsInvalid)
throw new InvalidOperationException("The buffer is invalid.");
Span.Fill(value);
}
#endregion
public ref T this[int index]
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
if (IsInvalid)
throw new InvalidOperationException("The buffer is invalid.");
if (index >= (Length))
throw new IndexOutOfRangeException();
unsafe
{
return ref Unsafe.Add(ref Unsafe.AsRef<T>(_VoidPointer), index);
}
}
}
#region Fields
private static readonly Type ElementType = typeof(T);
private static readonly ulong ElementSizeInBytes = (ulong) JemUtil.SizeOfStruct<T>();
private ulong _SizeInBytes;
private int _Length;
private IntPtr _Ptr;
private unsafe void* _VoidPointer;
private long _Timestamp;
private Span<T> _Span;
#endregion
}
}
================================================
FILE: jemalloc.Api/BufferHelpers.cs
================================================
//Based on SpanHelpers.cs
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
namespace jemalloc
{
internal static partial class BufferHelpers
{
public static int IndexOf(ref byte searchSpace, int searchSpaceLength, ref byte value, int valueLength)
{
Debug.Assert(searchSpaceLength >= 0);
Debug.Assert(valueLength >= 0);
if (valueLength == 0)
return 0; // A zero-length sequence is always treated as "found" at the start of the search space.
byte valueHead = value;
ref byte valueTail = ref Unsafe.Add(ref value, 1);
int valueTailLength = valueLength - 1;
int index = 0;
for (; ; )
{
Debug.Assert(0 <= index && index <= searchSpaceLength); // Ensures no deceptive underflows in the computation of "remainingSearchSpaceLength".
int remainingSearchSpaceLength = searchSpaceLength - index - valueTailLength;
if (remainingSearchSpaceLength <= 0)
break; // The unsearched portion is now shorter than the sequence we're looking for. So it can't be there.
// Do a quick search for the first element of "value".
int relativeIndex = IndexOf(ref Unsafe.Add(ref searchSpace, index), valueHead, remainingSearchSpaceLength);
if (relativeIndex == -1)
break;
index += relativeIndex;
// Found the first element of "value". See if the tail matches.
if (SequenceEqual(ref Unsafe.Add(ref searchSpace, index + 1), ref valueTail, valueTailLength))
return index; // The tail matched. Return a successful find.
index++;
}
return -1;
}
public static int IndexOfAny(ref byte searchSpace, int searchSpaceLength, ref byte value, int valueLength)
{
Debug.Assert(searchSpaceLength >= 0);
Debug.Assert(valueLength >= 0);
if (valueLength == 0)
return 0; // A zero-length sequence is always treated as "found" at the start of the search space.
int index = -1;
for (int i = 0; i < valueLength; i++)
{
var tempIndex = IndexOf(ref searchSpace, Unsafe.Add(ref value, i), searchSpaceLength);
if (tempIndex != -1)
{
index = (index == -1 || index > tempIndex) ? tempIndex : index;
}
}
return index;
}
private const ulong XorPowerOfTwoToHighByte = (0x07ul |
0x06ul << 8 |
0x05ul << 16 |
0x04ul << 24 |
0x03ul << 32 |
0x02ul << 40 |
0x01ul << 48) + 1;
public static int IndexOf<T>(ref T searchSpace, int searchSpaceLength, ref T value, int valueLength)
where T : IEquatable<T>
{
Debug.Assert(searchSpaceLength >= 0);
Debug.Assert(valueLength >= 0);
if (valueLength == 0)
return 0; // A zero-length sequence is always treated as "found" at the start of the search space.
T valueHead = value;
ref T valueTail = ref Unsafe.Add(ref value, 1);
int valueTailLength = valueLength - 1;
int index = 0;
for (;;)
{
Debug.Assert(0 <= index && index <= searchSpaceLength); // Ensures no deceptive underflows in the computation of "remainingSearchSpaceLength".
int remainingSearchSpaceLength = searchSpaceLength - index - valueTailLength;
if (remainingSearchSpaceLength <= 0)
break; // The unsearched portion is now shorter than the sequence we're looking for. So it can't be there.
// Do a quick search for the first element of "value".
int relativeIndex = IndexOf(ref Unsafe.Add(ref searchSpace, index), valueHead, remainingSearchSpaceLength);
if (relativeIndex == -1)
break;
index += relativeIndex;
// Found the first element of "value". See if the tail matches.
if (SequenceEqual(ref Unsafe.Add(ref searchSpace, index + 1), ref valueTail, valueTailLength))
return index; // The tail matched. Return a successful find.
index++;
}
return -1;
}
public static unsafe int IndexOf<T>(ref T searchSpace, T value, int length)
where T : IEquatable<T>
{
Debug.Assert(length >= 0);
IntPtr index = (IntPtr)0; // Use IntPtr for arithmetic to avoid unnecessary 64->32->64 truncations
while (length >= 8)
{
length -= 8;
if (value.Equals(Unsafe.Add(ref searchSpace, index)))
goto Found;
if (value.Equals(Unsafe.Add(ref searchSpace, index + 1)))
goto Found1;
if (value.Equals(Unsafe.Add(ref searchSpace, index + 2)))
goto Found2;
if (value.Equals(Unsafe.Add(ref searchSpace, index + 3)))
goto Found3;
if (value.Equals(Unsafe.Add(ref searchSpace, index + 4)))
goto Found4;
if (value.Equals(Unsafe.Add(ref searchSpace, index + 5)))
goto Found5;
if (value.Equals(Unsafe.Add(ref searchSpace, index + 6)))
goto Found6;
if (value.Equals(Unsafe.Add(ref searchSpace, index + 7)))
goto Found7;
index += 8;
}
if (length >= 4)
{
length -= 4;
if (value.Equals(Unsafe.Add(ref searchSpace, index)))
goto Found;
if (value.Equals(Unsafe.Add(ref searchSpace, index + 1)))
goto Found1;
if (value.Equals(Unsafe.Add(ref searchSpace, index + 2)))
goto Found2;
if (value.Equals(Unsafe.Add(ref searchSpace, index + 3)))
goto Found3;
index += 4;
}
while (length > 0)
{
if (value.Equals(Unsafe.Add(ref searchSpace, index)))
goto Found;
index += 1;
length--;
}
return -1;
Found: // Workaround for https://github.com/dotnet/coreclr/issues/13549
return (int)(byte*)index;
Found1:
return (int)(byte*)(index + 1);
Found2:
return (int)(byte*)(index + 2);
Found3:
return (int)(byte*)(index + 3);
Found4:
return (int)(byte*)(index + 4);
Found5:
return (int)(byte*)(index + 5);
Found6:
return (int)(byte*)(index + 6);
Found7:
return (int)(byte*)(index + 7);
}
public static bool SequenceEqual<T>(ref T first, ref T second, int length)
where T : IEquatable<T>
{
Debug.Assert(length >= 0);
if (Unsafe.AreSame(ref first, ref second))
goto Equal;
IntPtr index = (IntPtr)0; // Use IntPtr for arithmetic to avoid unnecessary 64->32->64 truncations
while (length >= 8)
{
length -= 8;
if (!Unsafe.Add(ref first, index).Equals(Unsafe.Add(ref second, index)))
goto NotEqual;
if (!Unsafe.Add(ref first, index + 1).Equals(Unsafe.Add(ref second, index + 1)))
goto NotEqual;
if (!Unsafe.Add(ref first, index + 2).Equals(Unsafe.Add(ref second, index + 2)))
goto NotEqual;
if (!Unsafe.Add(ref first, index + 3).Equals(Unsafe.Add(ref second, index + 3)))
goto NotEqual;
if (!Unsafe.Add(ref first, index + 4).Equals(Unsafe.Add(ref second, index + 4)))
goto NotEqual;
if (!Unsafe.Add(ref first, index + 5).Equals(Unsafe.Add(ref second, index + 5)))
goto NotEqual;
if (!Unsafe.Add(ref first, index + 6).Equals(Unsafe.Add(ref second, index + 6)))
goto NotEqual;
if (!Unsafe.Add(ref first, index + 7).Equals(Unsafe.Add(ref second, index + 7)))
goto NotEqual;
index += 8;
}
if (length >= 4)
{
length -= 4;
if (!Unsafe.Add(ref first, index).Equals(Unsafe.Add(ref second, index)))
goto NotEqual;
if (!Unsafe.Add(ref first, index + 1).Equals(Unsafe.Add(ref second, index + 1)))
goto NotEqual;
if (!Unsafe.Add(ref first, index + 2).Equals(Unsafe.Add(ref second, index + 2)))
goto NotEqual;
if (!Unsafe.Add(ref first, index + 3).Equals(Unsafe.Add(ref second, index + 3)))
goto NotEqual;
index += 4;
}
while (length > 0)
{
if (!Unsafe.Add(ref first, index).Equals(Unsafe.Add(ref second, index)))
goto NotEqual;
index += 1;
length--;
}
Equal:
return true;
NotEqual: // Workaround for https://github.com/dotnet/coreclr/issues/13549
return false;
}
/// <summary>
/// Implements the copy functionality used by Span and ReadOnlySpan.
///
/// NOTE: Fast span implements TryCopyTo in corelib and therefore this implementation
/// is only used by portable span. The code must live in code that only compiles
/// for portable span which means either each individual span implementation
/// of this shared code file. Other shared SpanHelper.X.cs files are compiled
/// for both portable and fast span implementations.
/// </summary>
public static unsafe void CopyTo<T>(ref T dst, int dstLength, ref T src, int srcLength)
{
Debug.Assert(dstLength != 0);
IntPtr srcByteCount = Unsafe.ByteOffset(ref src, ref Unsafe.Add(ref src, srcLength));
IntPtr dstByteCount = Unsafe.ByteOffset(ref dst, ref Unsafe.Add(ref dst, dstLength));
IntPtr diff = Unsafe.ByteOffset(ref src, ref dst);
bool isOverlapped = (sizeof(IntPtr) == sizeof(int))
? (uint)diff < (uint)srcByteCount || (uint)diff > (uint)-(int)dstByteCount
: (ulong)diff < (ulong)srcByteCount || (ulong)diff > (ulong)-(long)dstByteCount;
if (!isOverlapped && !BufferHelpers.IsReferenceOrContainsReferences<T>())
{
ref byte dstBytes = ref Unsafe.As<T, byte>(ref dst);
ref byte srcBytes = ref Unsafe.As<T, byte>(ref src);
ulong byteCount = (ulong)srcByteCount;
ulong index = 0;
while (index < byteCount)
{
uint blockSize = (byteCount - index) > uint.MaxValue ? uint.MaxValue : (uint)(byteCount - index);
Unsafe.CopyBlock(
ref Unsafe.Add(ref dstBytes, (IntPtr)index),
ref Unsafe.Add(ref srcBytes, (IntPtr)index),
blockSize);
index += blockSize;
}
}
else
{
bool srcGreaterThanDst = (sizeof(IntPtr) == sizeof(int))
? (uint)diff > (uint)-(int)dstByteCount
: (ulong)diff > (ulong)-(long)dstByteCount;
int direction = srcGreaterThanDst ? 1 : -1;
int runCount = srcGreaterThanDst ? 0 : srcLength - 1;
int loopCount = 0;
for (; loopCount < (srcLength & ~7); loopCount += 8)
{
Unsafe.Add<T>(ref dst, runCount + direction * 0) = Unsafe.Add<T>(ref src, runCount + direction * 0);
Unsafe.Add<T>(ref dst, runCount + direction * 1) = Unsafe.Add<T>(ref src, runCount + direction * 1);
Unsafe.Add<T>(ref dst, runCount + direction * 2) = Unsafe.Add<T>(ref src, runCount + direction * 2);
Unsafe.Add<T>(ref dst, runCount + direction * 3) = Unsafe.Add<T>(ref src, runCount + direction * 3);
Unsafe.Add<T>(ref dst, runCount + direction * 4) = Unsafe.Add<T>(ref src, runCount + direction * 4);
Unsafe.Add<T>(ref dst, runCount + direction * 5) = Unsafe.Add<T>(ref src, runCount + direction * 5);
Unsafe.Add<T>(ref dst, runCount + direction * 6) = Unsafe.Add<T>(ref src, runCount + direction * 6);
Unsafe.Add<T>(ref dst, runCount + direction * 7) = Unsafe.Add<T>(ref src, runCount + direction * 7);
runCount += direction * 8;
}
if (loopCount < (srcLength & ~3))
{
Unsafe.Add<T>(ref dst, runCount + direction * 0) = Unsafe.Add<T>(ref src, runCount + direction * 0);
Unsafe.Add<T>(ref dst, runCount + direction * 1) = Unsafe.Add<T>(ref src, runCount + direction * 1);
Unsafe.Add<T>(ref dst, runCount + direction * 2) = Unsafe.Add<T>(ref src, runCount + direction * 2);
Unsafe.Add<T>(ref dst, runCount + direction * 3) = Unsafe.Add<T>(ref src, runCount + direction * 3);
runCount += direction * 4;
loopCount += 4;
}
for (; loopCount < srcLength; ++loopCount)
{
Unsafe.Add<T>(ref dst, runCount) = Unsafe.Add<T>(ref src, runCount);
runCount += direction;
}
}
}
/// <summary>
/// Computes "start + index * sizeof(T)", using the unsigned IntPtr-sized multiplication for 32 and 64 bits.
///
/// Assumptions:
/// Start and index are non-negative, and already pre-validated to be within the valid range of their containing Span.
///
/// If the byte length (Span.Length * sizeof(T)) does an unsigned overflow (i.e. the buffer wraps or is too big to fit within the address space),
/// the behavior is undefined.
///
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static IntPtr Add<T>(this IntPtr start, int index)
{
Debug.Assert(start.ToInt64() >= 0);
Debug.Assert(index >= 0);
unsafe
{
if (sizeof(IntPtr) == sizeof(int))
{
// 32-bit path.
uint byteLength = (uint)index * (uint)Unsafe.SizeOf<T>();
return (IntPtr)(((byte*)start) + byteLength);
}
else
{
// 64-bit path.
ulong byteLength = (ulong)index * (ulong)Unsafe.SizeOf<T>();
return (IntPtr)(((byte*)start) + byteLength);
}
}
}
/// <summary>
/// Determine if a type is eligible for storage in unmanaged memory.
/// Portable equivalent of RuntimeHelpers.IsReferenceOrContainsReferences{T}()
/// </summary>
public static bool IsReferenceOrContainsReferences<T>() => PerTypeValues<T>.IsReferenceOrContainsReferences;
private static bool IsReferenceOrContainsReferencesCore(Type type)
{
if (type.GetTypeInfo().IsPrimitive) // This is hopefully the common case. All types that return true for this are value types w/out embedded references.
return false;
if (!type.GetTypeInfo().IsValueType)
return true;
// If type is a Nullable<> of something, unwrap it first.
Type underlyingNullable = Nullable.GetUnderlyingType(type);
if (underlyingNullable != null)
type = underlyingNullable;
if (type.GetTypeInfo().IsEnum)
return false;
foreach (FieldInfo field in type.GetTypeInfo().DeclaredFields)
{
if (field.IsStatic)
continue;
if (IsReferenceOrContainsReferencesCore(field.FieldType))
return true;
}
return false;
}
public static bool IsReferenceOrContainsReferences(Type type, out FieldInfo referenceField)
{
referenceField = null;
if (type.GetTypeInfo().IsPrimitive) // This is hopefully the common case. All types that return true for this are value types w/out embedded references.
return false;
if (!type.GetTypeInfo().IsValueType)
return true;
// If type is a Nullable<> of something, unwrap it first.
Type underlyingNullable = Nullable.GetUnderlyingType(type);
if (underlyingNullable != null)
type = underlyingNullable;
if (type.GetTypeInfo().IsEnum)
return false;
foreach (FieldInfo field in type.GetTypeInfo().DeclaredFields)
{
if (field.IsStatic)
continue;
if (IsReferenceOrContainsReferences(field.FieldType, out referenceField))
{
referenceField = field;
return true;
}
}
return false;
}
public static class PerTypeValues<T>
{
//
// Latch to ensure that excruciatingly expensive validation check for constructing a Span around a raw pointer is done
// only once per type.
//
public static readonly bool IsReferenceOrContainsReferences = IsReferenceOrContainsReferencesCore(typeof(T));
public static readonly T[] EmptyArray = new T[0];
public static readonly IntPtr ArrayAdjustment = MeasureArrayAdjustment();
// Array header sizes are a runtime implementation detail and aren't the same across all runtimes. (The CLR made a tweak after 4.5, and Mono has an extra Bounds pointer.)
private static IntPtr MeasureArrayAdjustment()
{
T[] sampleArray = new T[1];
return Unsafe.ByteOffset<T>(ref Unsafe.As<JemPinnable<T>>(sampleArray).Data, ref sampleArray[0]);
}
}
public unsafe static void ClearLessThanPointerSized(byte* ptr, UIntPtr byteLength)
{
if (sizeof(UIntPtr) == sizeof(uint))
{
Unsafe.InitBlockUnaligned(ptr, 0, (uint)byteLength);
}
else
{
// PERF: Optimize for common case of length <= uint.MaxValue
ulong bytesRemaining = (ulong)byteLength;
uint bytesToClear = (uint)(bytesRemaining & uint.MaxValue);
Unsafe.InitBlockUnaligned(ptr, 0, bytesToClear);
bytesRemaining -= bytesToClear;
ptr += bytesToClear;
// Clear any bytes > uint.MaxValue
while (bytesRemaining > 0)
{
bytesToClear = (bytesRemaining >= uint.MaxValue) ? uint.MaxValue : (uint)bytesRemaining;
Unsafe.InitBlockUnaligned(ptr, 0, bytesToClear);
ptr += bytesToClear;
bytesRemaining -= bytesToClear;
}
}
}
public static unsafe void ClearLessThanPointerSized(ref byte b, UIntPtr byteLength)
{
if (sizeof(UIntPtr) == sizeof(uint))
{
Unsafe.InitBlockUnaligned(ref b, 0, (uint)byteLength);
}
else
{
// PERF: Optimize for common case of length <= uint.MaxValue
ulong bytesRemaining = (ulong)byteLength;
uint bytesToClear = (uint)(bytesRemaining & uint.MaxValue);
Unsafe.InitBlockUnaligned(ref b, 0, bytesToClear);
bytesRemaining -= bytesToClear;
long byteOffset = bytesToClear;
// Clear any bytes > uint.MaxValue
while (bytesRemaining > 0)
{
bytesToClear = (bytesRemaining >= uint.MaxValue) ? uint.MaxValue : (uint)bytesRemaining;
ref byte bOffset = ref Unsafe.Add(ref b, (IntPtr)byteOffset);
Unsafe.InitBlockUnaligned(ref bOffset, 0, bytesToClear);
byteOffset += bytesToClear;
bytesRemaining -= bytesToClear;
}
}
}
public unsafe static void ClearPointerSizedWithoutReferences(ref byte b, UIntPtr byteLength)
{
// TODO: Perhaps do switch casing to improve small size perf
var i = IntPtr.Zero;
while (i.LessThanEqual(byteLength - sizeof(Reg64)))
{
Unsafe.As<byte, Reg64>(ref Unsafe.Add<byte>(ref b, i)) = default(Reg64);
i += sizeof(Reg64);
}
if (i.LessThanEqual(byteLength - sizeof(Reg32)))
{
Unsafe.As<byte, Reg32>(ref Unsafe.Add<byte>(ref b, i)) = default(Reg32);
i += sizeof(Reg32);
}
if (i.LessThanEqual(byteLength - sizeof(Reg16)))
{
Unsafe.As<byte, Reg16>(ref Unsafe.Add<byte>(ref b, i)) = default(Reg16);
i += sizeof(Reg16);
}
if (i.LessThanEqual(byteLength - sizeof(long)))
{
Unsafe.As<byte, long>(ref Unsafe.Add<byte>(ref b, i)) = 0;
i += sizeof(long);
}
// JIT: Should elide this if 64-bit
if (sizeof(IntPtr) == sizeof(int))
{
if (i.LessThanEqual(byteLength - sizeof(int)))
{
Unsafe.As<byte, int>(ref Unsafe.Add<byte>(ref b, i)) = 0;
i += sizeof(int);
}
}
}
public unsafe static void ClearPointerSizedWithReferences(ref IntPtr ip, UIntPtr pointerSizeLength)
{
// TODO: Perhaps do switch casing to improve small size perf
var i = IntPtr.Zero;
var n = IntPtr.Zero;
while ((n = i + 8).LessThanEqual(pointerSizeLength))
{
Unsafe.Add<IntPtr>(ref ip, i + 0) = default(IntPtr);
Unsafe.Add<IntPtr>(ref ip, i + 1) = default(IntPtr);
Unsafe.Add<IntPtr>(ref ip, i + 2) = default(IntPtr);
Unsafe.Add<IntPtr>(ref ip, i + 3) = default(IntPtr);
Unsafe.Add<IntPtr>(ref ip, i + 4) = default(IntPtr);
Unsafe.Add<IntPtr>(ref ip, i + 5) = default(IntPtr);
Unsafe.Add<IntPtr>(ref ip, i + 6) = default(IntPtr);
Unsafe.Add<IntPtr>(ref ip, i + 7) = default(IntPtr);
i = n;
}
if ((n = i + 4).LessThanEqual(pointerSizeLength))
{
Unsafe.Add<IntPtr>(ref ip, i + 0) = default(IntPtr);
Unsafe.Add<IntPtr>(ref ip, i + 1) = default(IntPtr);
Unsafe.Add<IntPtr>(ref ip, i + 2) = default(IntPtr);
Unsafe.Add<IntPtr>(ref ip, i + 3) = default(IntPtr);
i = n;
}
if ((n = i + 2).LessThanEqual(pointerSizeLength))
{
Unsafe.Add<IntPtr>(ref ip, i + 0) = default(IntPtr);
Unsafe.Add<IntPtr>(ref ip, i + 1) = default(IntPtr);
i = n;
}
if ((i + 1).LessThanEqual(pointerSizeLength))
{
Unsafe.Add<IntPtr>(ref ip, i) = default(IntPtr);
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private unsafe static bool LessThanEqual(this IntPtr index, UIntPtr length)
{
return (sizeof(UIntPtr) == sizeof(uint))
? (int)index <= (int)length
: (long)index <= (long)length;
}
[StructLayout(LayoutKind.Sequential, Size = 64)]
private struct Reg64 { }
[StructLayout(LayoutKind.Sequential, Size = 32)]
private struct Reg32 { }
[StructLayout(LayoutKind.Sequential, Size = 16)]
private struct Reg16 { }
}
}
================================================
FILE: jemalloc.Api/Extensions/TypeExtensions.cs
================================================
/*Based on the CodeProject article by Yuri Astrakhan and Sasha Goldshtein:
* https://www.codeproject.com/Articles/33382/Fast-Native-Structure-Reading-in-C-using-Dynamic-A
**/
using System;
using System.Collections.Generic;
using System.Reflection;
namespace jemalloc.Extensions
{
public static class TypeExtensions
{
/// <summary>
/// Gets a value indicating whether a type (or type's element type)
/// instance can be null in the underlying data store.
/// </summary>
/// <param name="type">A <see cref="System.Type"/> instance. </param>
/// <returns> True, if the type parameter is a closed generic nullable type; otherwise, False.</returns>
/// <remarks>Arrays of Nullable types are treated as Nullable types.</remarks>
public static bool IsNullable(this Type type)
{
while (type.IsArray)
type = type.GetElementType();
return (type.IsGenericType && type.GetGenericTypeDefinition() == typeof (Nullable<>));
}
/// <summary>
/// Returns the underlying type argument of the specified type.
/// </summary>
/// <param name="type">A <see cref="System.Type"/> instance. </param>
/// <returns><list>
/// <item>The type argument of the type parameter,
/// if the type parameter is a closed generic nullable type.</item>
/// <item>The underlying Type if the type parameter is an enum type.</item>
/// <item>Otherwise, the type itself.</item>
/// </list>
/// </returns>
public static Type GetUnderlyingType(this Type type)
{
if (type == null) throw new ArgumentNullException("type");
if (type.IsNullable())
type = type.GetGenericArguments()[0];
if (type.IsEnum)
type = Enum.GetUnderlyingType(type);
return type;
}
/// <summary>
/// Determines whether the specified types are considered equal.
/// </summary>
/// <param name="parent">A <see cref="System.Type"/> instance. </param>
/// <param name="child">A type possible derived from the <c>parent</c> type</param>
/// <returns>True, when an object instance of the type <c>child</c>
/// can be used as an object of the type <c>parent</c>; otherwise, false.</returns>
/// <remarks>Note that nullable types does not have a parent-child relation to it's underlying type.
/// For example, the 'int?' type (nullable int) and the 'int' type
/// aren't a parent and it's child.</remarks>
public static bool IsSameOrParent(Type parent, Type child)
{
if (parent == null) throw new ArgumentNullException("parent");
if (child == null) throw new ArgumentNullException("child");
if (parent == child ||
child.IsEnum && Enum.GetUnderlyingType(child) == parent ||
child.IsSubclassOf(parent))
{
return true;
}
if (parent.IsInterface)
{
var interfaces = child.GetInterfaces();
foreach (var t in interfaces)
if (t == parent)
return true;
}
return false;
}
/// <summary>
/// Recursively checks if the type with all of its members are expressable as a value type that may be cast to a pointer.
/// Equivalent to what compiler does to check for CS0208 error of this statement:
/// fixed (int* p = new int[5]) {}
///
/// An unmanaged-type is any type that isnt a reference-type and doesnt contain reference-type fields
/// at any level of nesting. In other words, an unmanaged-type is one of the following:
/// * sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal, or bool.
/// * Any enum-type.
/// * Any pointer-type.
/// * Any user-defined struct-type that contains fields of unmanaged-types only.
///
/// Strings are not in that list, even though you can use them in structs.
/// Fixed-size arrays of unmanaged-types are allowed.
/// </summary>
public static void ThrowIfNotUnmanagedType(this Type type)
{
ThrowIfNotUnmanagedType(type, new Stack<Type>(4));
}
private static void ThrowIfNotUnmanagedType(Type type, Stack<Type> typesStack)
{
if ((!type.IsValueType && !type.IsPointer) || type.IsGenericType || type.IsGenericParameter || type.IsArray)
throw new ArgumentException(String.Format("Type {0} is not an unmanaged type", type.FullName));
if (!type.IsPrimitive && !type.IsEnum && !type.IsPointer)
for (var p = type.DeclaringType; p != null; p = p.DeclaringType)
if (p.IsGenericTypeDefinition)
throw new ArgumentException(
String.Format("Type {0} contains a generic type definition declaring type {1}",
type.FullName, p.FullName));
try
{
typesStack.Push(type);
var fields = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
foreach (var f in fields)
if (!typesStack.Contains(f.FieldType))
ThrowIfNotUnmanagedType(f.FieldType);
}
catch (Exception ex)
{
throw new ArgumentException(
String.Format("Error in subtype of type {0}. See InnerException.", type.FullName), ex);
}
finally
{
typesStack.Pop();
}
}
/// <summary>
/// Substitutes the elements of an array of types for the type parameters
/// of the current generic type definition and returns a Type object
/// representing the resulting constructed type.
/// </summary>
/// <param name="type">A <see cref="System.Type"/> instance.</param>
/// <param name="typeArguments">An array of types to be substituted for
/// the type parameters of the current generic type.</param>
/// <returns>A Type representing the constructed type formed by substituting
/// the elements of <paramref name="typeArguments"/> for the type parameters
/// of the current generic type.</returns>
/// <seealso cref="System.Type.MakeGenericType"/>
public static Type TranslateGenericParameters(this Type type, Type[] typeArguments)
{
// 'T paramName' case
//
if (type.IsGenericParameter)
return typeArguments[type.GenericParameterPosition];
// 'List<T> paramName' or something like that.
//
if (type.IsGenericType && type.ContainsGenericParameters)
{
Type[] genArgs = type.GetGenericArguments();
for (int i = 0; i < genArgs.Length; ++i)
genArgs[i] = TranslateGenericParameters(genArgs[i], typeArguments);
return type.GetGenericTypeDefinition().MakeGenericType(genArgs);
}
// Non-generic type.
//
return type;
}
}
}
================================================
FILE: jemalloc.Api/ExtentHooks.cs
================================================
using System;
using System.Runtime.InteropServices;
using System.Security;
namespace jemalloc
{
public unsafe partial class ExtentHooks : IDisposable
{
[StructLayout(LayoutKind.Explicit, Size = 72)]
public partial struct __Internal
{
[FieldOffset(0)]
internal global::System.IntPtr alloc;
[FieldOffset(8)]
internal global::System.IntPtr dalloc;
[FieldOffset(16)]
internal global::System.IntPtr destroy;
[FieldOffset(24)]
internal global::System.IntPtr commit;
[FieldOffset(32)]
internal global::System.IntPtr decommit;
[FieldOffset(40)]
internal global::System.IntPtr purge_lazy;
[FieldOffset(48)]
internal global::System.IntPtr purge_forced;
[FieldOffset(56)]
internal global::System.IntPtr split;
[FieldOffset(64)]
internal global::System.IntPtr merge;
[SuppressUnmanagedCodeSecurity]
[DllImport("jemalloc", CallingConvention = global::System.Runtime.InteropServices.CallingConvention.Cdecl,
EntryPoint = "??0extent_hooks_s@@QEAA@AEBU0@@Z")]
internal static extern global::System.IntPtr cctor(global::System.IntPtr instance, global::System.IntPtr _0);
}
public global::System.IntPtr __Instance { get; protected set; }
protected int __PointerAdjustment;
internal static readonly global::System.Collections.Concurrent.ConcurrentDictionary<IntPtr, global::jemalloc.ExtentHooks> NativeToManagedMap = new global::System.Collections.Concurrent.ConcurrentDictionary<IntPtr, global::jemalloc.ExtentHooks>();
protected void*[] __OriginalVTables;
protected bool __ownsNativeInstance;
internal static global::jemalloc.ExtentHooks __CreateInstance(global::System.IntPtr native, bool skipVTables = false)
{
return new global::jemalloc.ExtentHooks(native.ToPointer(), skipVTables);
}
internal static global::jemalloc.ExtentHooks __CreateInstance(global::jemalloc.ExtentHooks.__Internal native, bool skipVTables = false)
{
return new global::jemalloc.ExtentHooks(native, skipVTables);
}
private static void* __CopyValue(global::jemalloc.ExtentHooks.__Internal native)
{
var ret = Marshal.AllocHGlobal(sizeof(global::jemalloc.ExtentHooks.__Internal));
*(global::jemalloc.ExtentHooks.__Internal*)ret = native;
return ret.ToPointer();
}
private ExtentHooks(global::jemalloc.ExtentHooks.__Internal native, bool skipVTables = false)
: this(__CopyValue(native), skipVTables)
{
__ownsNativeInstance = true;
NativeToManagedMap[__Instance] = this;
}
protected ExtentHooks(void* native, bool skipVTables = false)
{
if (native == null)
return;
__Instance = new global::System.IntPtr(native);
}
public ExtentHooks()
{
__Instance = Marshal.AllocHGlobal(sizeof(global::jemalloc.ExtentHooks.__Internal));
__ownsNativeInstance = true;
NativeToManagedMap[__Instance] = this;
}
public ExtentHooks(global::jemalloc.ExtentHooks _0)
{
__Instance = Marshal.AllocHGlobal(sizeof(global::jemalloc.ExtentHooks.__Internal));
__ownsNativeInstance = true;
NativeToManagedMap[__Instance] = this;
*((global::jemalloc.ExtentHooks.__Internal*)__Instance) = *((global::jemalloc.ExtentHooks.__Internal*)_0.__Instance);
}
public void Dispose()
{
Dispose(disposing: true);
}
public virtual void Dispose(bool disposing)
{
if (__Instance == IntPtr.Zero)
return;
global::jemalloc.ExtentHooks __dummy;
NativeToManagedMap.TryRemove(__Instance, out __dummy);
if (__ownsNativeInstance)
Marshal.FreeHGlobal(__Instance);
__Instance = IntPtr.Zero;
}
}
}
================================================
FILE: jemalloc.Api/FixedBuffer.cs
================================================
using System;
using System.Buffers;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading;
namespace jemalloc
{
[StructLayout(LayoutKind.Sequential)]
[DebuggerDisplay("{DebuggerDisplay(),nq}")]
public readonly struct FixedBuffer<T> : IDisposable, IRetainable, IEquatable<FixedBuffer<T>>, IEnumerable<T> where T : struct, IEquatable<T>, IComparable<T>, IConvertible
{
#region Constructors
public FixedBuffer(int length)
{
_Ptr = IntPtr.Zero;
_Length = 0;
_SizeInBytes = 0;
_Timestamp = 0;
IsReadOnly = false;
AllocateThreadId = 0;
Rid = JemUtil.Rng.Next(0, 4096);
if (length == 0)
{
throw new ArgumentException("FixedBuffer Length cannot be zero.");
}
ThrowIfTypeNotPrimitive();
long t = DateTime.UtcNow.Ticks;
int th = Thread.CurrentThread.ManagedThreadId;
_Ptr = Jem.AllocateFixedBuffer<T>((ulong)length, ElementSizeInBytes, t, th, Rid);
if (_Ptr != IntPtr.Zero)
{
_Length = length;
_SizeInBytes = (ulong)_Length * ElementSizeInBytes;
_Timestamp = t;
AllocateThreadId = th;
}
else throw new OutOfMemoryException($"Could not allocate {(ulong)_Length * ElementSizeInBytes} bytes for {Name}");
}
public FixedBuffer(int length, bool isReadOnly) : this(length)
{
IsReadOnly = true;
}
public FixedBuffer(T[] array) : this(array.Length)
{
ReadOnlySpan<T> arraySpan = new ReadOnlySpan<T>(array);
arraySpan.CopyTo(this.WriteSpan);
}
public FixedBuffer(Span<T> span) : this(span.Length)
{
span.CopyTo(this.WriteSpan);
}
public FixedBuffer(ReadOnlySpan<T> span) : this(span.Length)
{
IsReadOnly = true;
span.CopyTo(this.WriteSpan);
}
#endregion
#region Implemented members
public void Retain()
{
ThrowIfInvalid();
Jem.IncrementRefCount(_Ptr);
}
public bool Release()
{
ThrowIfInvalid();
if (RefCount == 0)
{
return false;
}
else
{
Jem.DecrementRefCount(_Ptr);
return true;
}
}
bool IEquatable<FixedBuffer<T>>.Equals(FixedBuffer<T> buffer)
{
ThrowIfInvalid();
return this._Ptr == buffer.Ptr && this.Length == buffer.Length && this._Timestamp == buffer.Timestamp
&& this.AllocateThreadId == buffer.AllocateThreadId && this.Rid == buffer.Rid;
}
public IEnumerator<T> GetEnumerator() => new FixedBufferEnumerator<T>(this);
IEnumerator IEnumerable.GetEnumerator() => new FixedBufferEnumerator<T>(this);
#region Disposer
void IDisposable.Dispose()
{
if (IsRetained)
{
throw new InvalidOperationException($"FixedBuffer<{typeof(T)}[{_Length}] has outstanding references.");
}
Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
Free();
}
#endregion
#endregion
#region Properties
#region Public
public bool IsInvalid => _Ptr == IntPtr.Zero || !Jem.FixedBufferIsAllocatedWith(_Ptr, _SizeInBytes, _Timestamp, AllocateThreadId, Rid);
public bool IsValid => !IsInvalid;
public int RefCount
{
get
{
ThrowIfInvalid();
return Jem.GetRefCount(_Ptr);
}
}
public bool IsRetained => RefCount > 0;
public bool IsReadOnly { get; }
public int Length
{
get
{
ThrowIfInvalid();
return _Length;
}
}
public ulong Size
{
get
{
ThrowIfInvalid();
return _SizeInBytes;
}
}
public unsafe ReadOnlySpan<T> Span
{
get
{
ThrowIfInvalid();
return new ReadOnlySpan<T>(_Ptr.ToPointer(), _Length);
}
}
internal IntPtr Ptr
{
get
{
ThrowIfInvalid();
return _Ptr;
}
}
#endregion
internal long Timestamp
{
get
{
return _Timestamp;
}
}
internal unsafe Span<T> WriteSpan
{
get
{
ThrowIfInvalid();
return new Span<T>(_Ptr.ToPointer(), _Length);
}
}
#endregion
#region Methods
public void Acquire() => Retain();
public bool Free()
{
if (IsInvalid)
{
return false;
}
if(IsRetained)
{
return false;
}
return Jem.FreeFixedBuffer(_Ptr);
}
public void Fill(T value)
{
WriteSpan.Fill(value);
}
public void CopyTo(T[] array)
{
WriteSpan.CopyTo(new Span<T>(array));
}
public T[] CopyToArray()
{
T[] array = new T[Length];
WriteSpan.CopyTo(new Span<T>(array));
return array;
}
public T[] CopyToArray(T[] array)
{
if (_Length != array.Length)
{
throw new ArgumentException($"Array length {array.Length} is not the same as length {_Length} of {Name}.");
}
else
{
Span.CopyTo(new Span<T>(array));
return array;
}
}
public T[] CopyToArrayAndFree()
{
T[] array = CopyToArray();
Free();
return array;
}
public bool EqualTo(T[] array)
{
ThrowIfInvalid();
if (_Length != array.Length)
{
return false;
}
else
{
ReadOnlySpan<T> span = new ReadOnlySpan<T>(array);
bool ret = this.Span.SequenceEqual(span);
return ret;
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe ReadOnlySpan<T> AcquireSpan()
{
Acquire();
return new ReadOnlySpan<T>((void*) _Ptr, (int)Length);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe ReadOnlySpan<C> AcquireSpan<C>() where C : struct, IEquatable<T>, IComparable<T>, IConvertible
{
int size = checked((int)(Size / (ulong)JemUtil.SizeOfStruct<C>()));
if (size == 0)
{
throw new ArgumentException($"Type {typeof(T).Name} is too small to be reinterpreted as {typeof(C).Name}.");
}
else
{
Acquire();
return new ReadOnlySpan<C>((void*)_Ptr, size);
}
}
public ReadOnlySpan<T> Slice(int start, int length)
{
return Span.Slice(start, length);
}
public unsafe void * PtrTo(int index)
{
return BufferHelpers.Add<T>(_Ptr, index).ToPointer();
}
public Vector<T> AcquireAsSingleVector()
{
if (this._Length != Vector<T>.Count)
{
throw new InvalidOperationException($"The length of the array must be {Vector<T>.Count} elements to create a vector of type {JemUtil.CLRType<T>().Name}.");
}
ReadOnlySpan<T> span = AcquireSpan();
ReadOnlySpan<Vector<T>> vector = span.NonPortableCast<T, Vector<T>>();
return vector[0];
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe ReadOnlySpan<Vector<T>> AcquireVectorSpan()
{
ThrowIfNotVectorizable();
ThrowIfInvalid();
return new ReadOnlySpan<Vector<T>>(_Ptr.ToPointer(), _Length / JemUtil.VectorLength<T>());
}
public unsafe Span<T> AcquireWriteSpan()
{
Acquire();
return new Span<T>((void*)_Ptr, _Length);
}
public unsafe Span<Vector<T>> AcquireVectorWriteSpan()
{
ThrowIfNotVectorizable();
Acquire();
return new Span<Vector<T>>(_Ptr.ToPointer(), _Length / JemUtil.VectorLength<T>());
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal unsafe ref T Read(int index)
{
ref T ret = ref Unsafe.Add(ref Unsafe.AsRef<T>(_Ptr.ToPointer()), index);
return ref ret;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe ref C Read<C>(int index) where C : struct
{
//ref C ret = ref Unsafe.aAdd(ref Unsafe.AsRef<C>(_Ptr.ToPointer()), index);
//return re
return ref Unsafe.AsRef<C>(PtrTo(index));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe void Write<C>(int index, ref C value) where C : struct
{
Unsafe.Write(PtrTo(index), value);
}
internal unsafe Span<Vector<T>> WriteVectorSpan
{
get
{
ThrowIfInvalid();
return new Span<Vector<T>>(_Ptr.ToPointer(), _Length / JemUtil.VectorLength<T>());
}
}
internal void ThrowIfInvalid()
{
if (IsInvalid)
{
throw new InvalidOperationException($"{nameof(FixedBuffer<T>)}({this._Length}) is invalid.");
}
}
internal void ThrowIfIndexOutOfRange(int index)
{
if (index >= _Length)
{
throw new IndexOutOfRangeException($"Index {index} is greater than the maximum index of the buffer {_Length - 1}.");
}
else if (index < 0)
{
throw new IndexOutOfRangeException($"Index {index} is less than zero.");
}
}
internal void ThrowIfRefCountNonZero()
{
if (0 > 0)
{
throw new InvalidOperationException($"{nameof(FixedBuffer<T>)}({this._Length}) has RefCount .");
}
}
internal void ThrowIfReadOnly()
{
if (IsReadOnly)
{
throw new InvalidOperationException($"{nameof(FixedBuffer<T>)}({this._Length}) is read-only.");
}
}
internal void ThrowIfTypeNotPrimitive()
{
if (!typeof(T).IsPrimitive)
{
throw new ArgumentException($"The type {typeof(T).Name} is not a primitive type.");
}
}
internal void ThrowIfNotVectorizable()
{
if (!JemUtil.IsNumericType<T>() || _Length == 0 || (_Length % JemUtil.VectorLength<T>() != 0))
{
throw new InvalidOperationException("Buffer is not vectorizable.");
}
}
internal string Name => $"{nameof(FixedBuffer<T>)}({this._Length})";
private string DebuggerDisplay() => string.Format("{{{0}[{1}]}}", typeof(T).Name, Length);
#region Arithmetic
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void VectorFill(T value)
{
ThrowIfInvalid();
int c = JemUtil.VectorLength<T>();
int i;
Vector<T> fill = new Vector<T>(value);
Span<Vector<T>> s = WriteVectorSpan;
for (i = 0; i < s.Length; i ++)
{
s[i] = fill;
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void VectorMultiply(T value)
{
ThrowIfInvalid();
int c = JemUtil.VectorLength<T>();
int i;
T r;
Vector<T> mul = new Vector<T>(value);
for (i = 0; i < _Length - c; i += c)
{
Vector<T> f = Read<Vector<T>>(i);
Vector<T> result = f * mul;
Write(i, ref result);
}
for (; i < _Length; ++i)
{
r = GM<T>.Multiply(this[i], value);
Write(i, ref r);
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void VectorSqrt()
{
ThrowIfInvalid();
int c = JemUtil.VectorLength<T>();
int i;
T r;
for (i = 0; i < _Length - c; i += c)
{
Vector<T> f = Read<Vector<T>>(i);
Vector<T> result = Vector.SquareRoot(f);
Write(i, ref result);
}
for (; i < _Length; ++i)
{
r = JemUtil.ValToGenericStruct<double, T>(GM<T>.Sqrt(this[i]));
Write(i, ref r);
}
}
public unsafe bool VectorLessThanAll(T value, out int index)
{
ThrowIfInvalid();
index = -1;
bool r = true;
int c = Vector<T>.Count;
int i;
Vector<T> v = new Vector<T>(value);
Vector<T> O = Vector<T>.One;
for (i = 0; i <= _Length - c; i+= c)
{
Vector<T> s = Unsafe.Read<Vector<T>>(BufferHelpers.Add<T>(_Ptr, i).ToPointer());
Vector<T> vcmp = Vector.LessThan(s, v);
if (vcmp == O)
{
continue;
}
else
{
r = false;
for (int j = 0; j < c; j++)
{
if (vcmp[j].Equals(default))
{
index = i + j;
return r;
}
}
return r;
}
}
for (; i < _Length; ++i)
{
if (Read(i).CompareTo(value) >= 0)
{
r = false;
index = i;
return r;
}
}
return r;
}
#endregion
#endregion
#region Operators
public ref T this[int index]
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => ref this.Read(index);
}
public static implicit operator IntPtr (FixedBuffer<T> buffer)
{
return buffer._Ptr;
}
#endregion
#region Fields
private static readonly Type ElementType = typeof(T);
private static readonly ulong ElementSizeInBytes = (ulong) JemUtil.SizeOfStruct<T>();
private static readonly int VectorWidth = Vector<T>.Count;
private readonly IntPtr _Ptr;
private readonly ulong _SizeInBytes;
private readonly int _Length;
private readonly long _Timestamp;
internal readonly int AllocateThreadId;
internal readonly int Rid;
#endregion
}
}
================================================
FILE: jemalloc.Api/FixedBufferAllocation.cs
================================================
using System;
using System.Collections.Generic;
using System.Text;
namespace jemalloc
{
public readonly struct FixedBufferAllocation : IEquatable<FixedBufferAllocation>
{
#region Constructor
public FixedBufferAllocation(IntPtr ptr, ulong size, long timestamp, int tid, int rid)
{
this.Ptr = ptr;
this.Size = size;
this.TimeStamp = timestamp;
this.ThreadId = tid;
this.Rid = rid;
HashCode = JemUtil.CombineHashCodes(this.Ptr.GetHashCode(), this.Size.GetHashCode(), this.TimeStamp.GetHashCode(), this.ThreadId.GetHashCode(), this.Rid.GetHashCode());
}
#endregion
public override int GetHashCode()
{
return this.HashCode;
}
public override bool Equals(object obj)
{
if (obj is FixedBufferAllocation)
{
FixedBufferAllocation o = (FixedBufferAllocation)obj;
return this.HashCode == o.HashCode;
}
else
{
return false;
}
}
bool IEquatable<FixedBufferAllocation>.Equals(FixedBufferAllocation other)
{
return this.HashCode == other.HashCode;
}
public readonly IntPtr Ptr;
public readonly ulong Size;
public readonly long TimeStamp;
public readonly int ThreadId;
public readonly int Rid;
public readonly int HashCode;
}
public class FixedBufferComparator : IEqualityComparer<FixedBufferAllocation>
{
public bool Equals(FixedBufferAllocation l, FixedBufferAllocation r)
{
return l.HashCode == r.HashCode;
}
public int GetHashCode(FixedBufferAllocation a)
{
return a.HashCode;
}
}
}
================================================
FILE: jemalloc.Api/FixedBufferEnumerator.cs
================================================
using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Text;
namespace jemalloc
{
public class FixedBufferEnumerator<T> : IEnumerator, IEnumerator<T> where T : struct, IEquatable<T>, IComparable<T>, IConvertible
{
/// <summary>The SafeBuffer being enumerated.</summary>
private readonly FixedBuffer<T> _buffer;
/// <summary>The next index to yield.</summary>
private int _index;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal FixedBufferEnumerator(FixedBuffer<T> buffer)
{
_buffer = buffer;
_buffer.Acquire();
_index = -1;
}
/// <summary>Advances the enumerator to the next element of the buffer.</summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool MoveNext()
{
int index = _index + 1;
if (index < _buffer.Length)
{
_index = index;
return true;
}
else
{
return false;
}
}
public void Reset()
{
_index = -1;
}
/// <summary>Gets the element at the current position of the enumerator.</summary>
object IEnumerator.Current
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _buffer[_index];
}
public T Current
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _buffer[_index];
}
void IDisposable.Dispose()
{
_buffer.Release();
}
}
}
================================================
FILE: jemalloc.Api/GDI.cs
================================================
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
namespace jemalloc
{
public unsafe static partial class Win32
{
public enum BitmapCompressionMode
{
BI_RGB = 0x0000,
BI_RLE8 = 0x0001,
BI_RLE4 = 0x0002,
BI_BITFIELDS = 0x0003,
BI_JPEG = 0x0004,
BI_PNG = 0x0005,
BI_CMYK = 0x000B,
BI_CMYKRLE8 = 0x000C,
BI_CMYKRLE4 = 0x000D
}
[StructLayout(LayoutKind.Sequential)]
public struct BITMAPINFOHEADER
{
public uint biSize;
public int biWidth;
public int biHeight;
public ushort biPlanes;
public ushort biBitCount;
public BitmapCompressionMode biCompression;
public uint biSizeImage;
public int biXPelsPerMeter;
public int biYPelsPerMeter;
public uint biClrUsed;
public uint biClrImportant;
public void Init()
{
biSize = (uint)Marshal.SizeOf(this);
}
}
[StructLayout(LayoutKind.Sequential)]
public struct RGBQUAD
{
public byte rgbBlue;
public byte rgbGreen;
public byte rgbRed;
public byte rgbReserved;
}
public struct BITMAPINFO
{
BITMAPINFOHEADER bmiHeader;
RGBQUAD[] bmiColors;
}
[DllImport("gdi32.dll")]
static extern IntPtr CreateDIBitmap(IntPtr hdc, [In] ref BITMAPINFOHEADER lpbmih, uint fdwInit, byte[] lpbInit, [In] ref BITMAPINFO lpbmi, uint fuUsage);
}
}
================================================
FILE: jemalloc.Api/GenericMath.cs
================================================
using System;
using System.Collections.Generic;
using System.Text;
namespace jemalloc
{
public static class GM<TData> where TData : struct, IEquatable<TData>, IComparable<TData>, IConvertible
{
#region Constructor
static GM()
{
if (!JemUtil.IsNumericType<TData>())
{
throw new InvalidOperationException($"Type {typeof(TData).Name} is not a numeric type.");
}
}
#endregion
#region Properties
public static Random Rng { get; } = new Random();
#endregion
#region Methods
public static TData Const<TValue>(TValue v) where TValue : struct, IEquatable<TValue>, IComparable<TValue>, IConvertible
{
return (TData) Convert.ChangeType(v, typeof(TData));
}
public static TData Multiply(TData l, TData r)
{
Tuple<TData, TData> value = new Tuple<TData, TData>(l, r);
switch (value)
{
case Tuple<Byte, Byte> v:
return (TData)Convert.ChangeType(checked((byte)(v.Item1 * v.Item2)), typeof(TData));
case Tuple<SByte, SByte> v:
return (TData)Convert.ChangeType(checked((SByte)(v.Item1 * v.Item2)), typeof(TData));
case Tuple<UInt16, UInt16> v:
return (TData)Convert.ChangeType((checked((UInt16)(v.Item1 * v.Item2))), typeof(TData));
case Tuple<Int16, Int16> v:
return (TData)Convert.ChangeType(checked((Int16)(v.Item1 * v.Item2)), typeof(TData));
case Tuple<UInt32, UInt32> v:
return (TData)Convert.ChangeType(checked(v.Item1 * v.Item2), typeof(TData));
case Tuple<Int32, Int32> v:
return (TData)Convert.ChangeType(checked(v.Item1 * v.Item2), typeof(TData));
case Tuple<UInt64, UInt64> v:
return (TData)Convert.ChangeType(checked(v.Item1 * v.Item2), typeof(TData));
case Tuple<Int64, Int64> v:
return (TData)Convert.ChangeType(checked(v.Item1 * v.Item2), typeof(TData));
case Tuple<Single, Single> v:
return (TData)Convert.ChangeType(checked(v.Item1 * v.Item2), typeof(TData));
case Tuple<Double, Double> v:
return (TData)Convert.ChangeType(checked(v.Item1 * v.Item2), typeof(TData));
case Tuple<bool, bool> v:
throw new ArgumentException($"Cannot multiply 2 bools.");
default:
throw new Exception($"Unsupported math type: {typeof(TData).Name}");
}
}
public static double Sqrt(TData n)
{
switch (n)
{
case SByte v:
return checked(Math.Sqrt(v));
case Byte v:
return checked(Math.Sqrt(v));
case Int32 v:
return checked(Math.Sqrt(v));
case UInt32 v:
return checked(Math.Sqrt(v));
case Int16 v:
return checked(Math.Sqrt(v));
case UInt16 v:
return checked(Math.Sqrt(v));
case Int64 v:
return checked(Math.Sqrt(v));
case UInt64 v:
return checked(Math.Sqrt(v));
case Single v:
return checked(Math.Sqrt(v));
case Double v:
return checked(Math.Sqrt(v));
case bool v:
throw new ArgumentException($"Cannot get the square root of a bool.");
default:
throw new ArithmeticException();
}
}
public static double F(Func<double, double> f, TData n)
{
switch (n)
{
case SByte v:
return checked(f(v));
case Byte v:
return checked(f(v));
case Int32 v:
return checked(f(v));
case UInt32 v:
return checked(f(v));
case Int16 v:
return checked(f(v));
case UInt16 v:
return checked(f(v));
case Int64 v:
return checked(f(v));
case UInt64 v:
return checked(f(v));
case Single v:
return checked(f(v));
case Double v:
return checked(f(v));
case Boolean v:
throw new ArgumentException($"Cannot apply math functions to a bool.");
default:
throw new ArithmeticException();
}
}
public static TData Random()
{
TData e = default;
switch (e)
{
case SByte v:
return Const(checked((sbyte)Rng.Next(0, SByte.MaxValue)));
case Byte v:
return Const(checked((byte)Rng.Next(0, Byte.MaxValue)));
case Int32 v:
return Const(checked((int)Rng.Next(0, Int32.MaxValue)));
case UInt32 v:
return Const(checked((uint)Rng.Next(0, Int32.MaxValue)));
case Int16 v:
return Const(checked((short)Rng.Next(0, Int16.MaxValue)));
case UInt16 v:
return Const(checked((ushort)Rng.Next(0, UInt16.MaxValue)));
case Int64 v:
return Const(checked((long)(Rng.NextDouble() * Int64.MaxValue)));
case UInt64 v:
return Const(checked((ulong)(Rng.NextDouble() * UInt64.MaxValue)));
case Single v:
return Const(checked(((Single)(Rng.NextDouble() * Int64.MaxValue))));
case Double v:
return Const(checked((((double)Rng.NextDouble() * Int64.MaxValue))));
case Boolean v:
return Const(Convert.ToBoolean(Rng.Next(0, 1)));
default:
throw new ArithmeticException();
}
}
public static TData Random(double max)
{
return Const(checked((double)Rng.NextDouble() * max));
}
public static (TData, TData) RandomMultiplyFactorAndValue()
{
TData e = default;
TData max;
int factor = Rng.Next(0, 4);
switch (e)
{
case SByte v:
max = Random((sbyte)(sbyte.MaxValue / 4));
break;
case Byte v:
max = Random((byte)(byte.MaxValue / (byte) 4));
break;
case Int16 v:
max = Random((short)(short.MaxValue / (short)4));
break;
case UInt16 v:
max = Random((ushort)(ushort.MaxValue / (ushort)4));
break;
case Int32 v:
max = Random((int)(int.MaxValue / 4));
break;
case UInt32 v:
max = Random(uint.MaxValue / 4u);
break;
case Int64 v:
max = Random((long)(long.MaxValue / 4));
break;
case UInt64 v:
max = Random(ulong.MaxValue / 4u);
break;
case Double v:
max = Random((double)(long.MaxValue / 4));
break;
case Single v:
max = Random((Single)(long.MaxValue / 4));
break;
default:
throw new ArgumentException($"Cannot multiply type {nameof(TData)}.");
}
return (Const(factor), Const(max));
}
#endregion
}
}
================================================
FILE: jemalloc.Api/HugeArray.cs
================================================
using System;
using System.Collections.Generic;
using System.Text;
namespace jemalloc
{
public class HugeArray<T> : HugeBuffer<T> where T : struct, IEquatable<T>
{
public HugeArray(ulong length, params T[] values) : base(length, values) { }
}
}
================================================
FILE: jemalloc.Api/HugeBuffer.cs
================================================
using System;
using System.Buffers;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.Contracts;
using System.Numerics;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
using System.Runtime.ConstrainedExecution;
using System.Threading;
namespace jemalloc
{
public abstract class HugeBuffer<T> : SafeHandle, IRetainable, IDisposable, IEquatable<HugeBuffer<T>>, IEnumerable<T> where T : struct, IEquatable<T>
{
#region Constructors
protected HugeBuffer(ulong length, params T[] values) : base(IntPtr.Zero, true)
{
ulong l = (ulong)values.Length;
if (BufferHelpers.IsReferenceOrContainsReferences<T>())
{
throw new ArgumentException("Only structures without reference fields can be used with this class.");
}
if (l > length)
{
throw new ArgumentException("The length of the list of values must be smaller or equal to the length of the buffer");
}
SizeInBytes = NotAllocated;
base.SetHandle(Allocate(length));
if (IsAllocated)
{
CopyFrom(values);
}
}
#endregion
#region Overriden members
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
protected override bool ReleaseHandle()
{
bool r = Jem.Free(handle);
if (!r)
{
return false;
}
else
{
handle = IntPtr.Zero;
unsafe
{
voidPtr = (void*)0;
}
Length = 0;
SizeInBytes = 0;
return true;
}
}
public override bool IsInvalid => handle == IntPtr.Zero;
#region Disposer
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
protected override void Dispose(bool disposing)
{
if (disposing)
{
ThrowIfNotAllocatedOrInvalid();
ThrowIfRetained();
ReleaseHandle();
}
base.Dispose(disposing);
}
#endregion
#endregion
#region Implemented members
public void Retain() => Acquire();
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
public bool Release()
{
if (IsNotAllocated || IsInvalid)
{
return false;
}
else
{
Jem.DecrementRefCount(handle);
DangerousRelease();
return true;
}
}
public bool Equals(HugeBuffer<T> other)
{
ThrowIfNotAllocatedOrInvalid();
return this.handle == other.handle && this.Length == other.Length;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public IEnumerator<T> GetEnumerator() => new HugeBufferEnumerator<T>(this);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
IEnumerator IEnumerable.GetEnumerator() => new HugeBufferEnumerator<T>(this);
#endregion
#region Properties
public ulong Length { get; protected set; }
public ulong SizeInBytes { get; protected set; }
public bool IsNotAllocated => SizeInBytes == NotAllocated;
public bool IsAllocated => !IsNotAllocated;
public bool IsValid => !IsInvalid;
public bool IsRetained => _RefCount > 0;
public bool IsVectorizable { get; protected set; }
protected int _RefCount => Jem.GetRefCount(handle);
#endregion
#region Methods
#region Memory management
protected unsafe virtual IntPtr Allocate(ulong length)
{
if (length < 0)
throw new ArgumentOutOfRangeException("length");
Contract.EndContractBlock();
ulong s = checked(length * ElementSizeInBytes);
handle = Jem.Calloc(length, ElementSizeInBytes);
if (handle != IntPtr.Zero)
{
voidPtr = handle.ToPointer();
Length = length;
SizeInBytes = s;
InitSegments();
InitVectors();
}
return handle;
}
protected unsafe void InitSegments()
{
int n = (int)((Length - 1) / Int32.MaxValue) + 1;
segments = new IntPtr[n];
segments2 = new Tuple<IntPtr, int>[segments.Length];
segments[0] = handle;
segments2[0] = new Tuple<IntPtr, int>(handle, n == 1 ? (int)Length : Int32.MaxValue);
for (int i = 1; i < n; i++)
{
segments[i] = BufferHelpers.Add<T>(segments[i - 1], Int32.MaxValue);
if (i < n - 1)
{
segments2[i] = new Tuple<IntPtr, int>(segments[i], Int32.MaxValue);
}
}
segments2[n - 1] = new Tuple<IntPtr, int>(segments[n - 1], (int)(Length - (ulong)((n - 1) * Int32.MaxValue)));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
protected unsafe void InitVectors()
{
if (IsNumeric && Length % (ulong)VectorLength == 0 && SIMD)
{
IsVectorizable = true;
}
else
{
IsVectorizable = false;
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
protected int _GetSegmentIndex(ulong index)
{
return (int)(index / Int32.MaxValue);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
protected unsafe void _GetSegment(ulong index, out void* ptr, out int offset)
{
int s = _GetSegmentIndex(index);
int l = segments.Length;
ptr = segments[s].ToPointer();
offset = (int)(index - ((ulong)(s) * Int32.MaxValue));
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
protected unsafe Span<T> _GetSegmentSpan(ulong index)
{
int i = _GetSegmentIndex(index);
return new Span<T>(segments2[i].Item1.ToPointer(), segments2[i].Item2);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
protected unsafe Span<Vector<T>> _GetSegmentVectorSpan(ulong index)
{
int i = _GetSegmentIndex(index);
return new Span<Vector<T>>(segments2[i].Item1.ToPointer(), segments2[i].Item2 / VectorLength + 1);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
protected unsafe ref T _Read(ulong index)
{
// return (T*) (seg_ptr + byteOffset);
_GetSegment(index, out void* ptr, out int offset);
ref T ret = ref Unsafe.Add(ref Unsafe.AsRef<T>(ptr), offset);
return ref ret;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
protected unsafe T _Write(ulong index, T value)
{
// return (T*) (seg_ptr + byteOffset);
_GetSegment(index, out void* ptr, out int offset);
ref T v = ref Unsafe.AsRef<T>(BufferHelpers.Add<T>(new IntPtr(ptr), offset).ToPointer());
v = value;
return value;
}
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
public bool Acquire()
{
if (IsNotAllocated || IsInvalid)
return false;
bool success = false;
DangerousAddRef(ref success);
if (success)
{
Jem.IncrementRefCount(handle);
}
return success;
}
public bool Release(int n)
{
bool r = false;
for (int i = 0; i < n; i++)
{
r = Release();
if (r)
{
continue;
}
else
{
return r;
}
}
return r;
}
#endregion
#region Values
public bool EqualTo(T[] array)
{
ThrowIfNotAllocatedOrInvalid();
if (this.Length != (ulong)array.Length)
{
return false;
}
return _GetSegmentSpan(0).SequenceEqual(new ReadOnlySpan<T>(array));
}
public unsafe void Fill(T value)
{
ThrowIfNotAllocatedOrInvalid();
for (int i = 0; i < segments.Length; i++)
{
Span<T> s = new Span<T>(segments2[i].Item1.ToPointer(), segments2[i].Item2);
s.Fill(value);
}
}
public void CopyFrom(T[] array)
{
ThrowIfNotAllocatedOrInvalid();
new Span<T>(array).CopyTo(_GetSegmentSpan(0));
}
public T[] CopyToArray()
{
ThrowIfNotAllocatedOrInvalid();
if (this.Length > Int32.MaxValue)
{
throw new ArgumentOutOfRangeException("This length of this array exceeds the max length of a managed array.");
}
T[] a = new T[this.Length];
_GetSegmentSpan(0).CopyTo(new Span<T>(a));
return a;
}
public unsafe Span<C> GetSpan<C>(ulong index = 0, int length = 1) where C : struct, IEquatable<C>
{
ThrowIfNotAllocatedOrInvalid();
ThrowIfIndexOutOfRange(index);
ulong s = (index * (ulong) ElementSizeInBytes + (ulong) length * (ulong) Unsafe.SizeOf<C>());
if (s > SizeInBytes)
{
BufferSizeIsOutOfRange(s);
}
_GetSegment(index, out void* ptr, out int offset);
void* p = BufferHelpers.Add<T>(new IntPtr(ptr), offset).ToPointer();
return new Span<C>(p, length);
}
public unsafe Span<T> Slice(ulong start, ulong end)
{
ThrowIfNotAllocatedOrInvalid();
ThrowIfIndexOutOfRange(start);
ThrowIfIndexOutOfRange(end);
if (start >= end)
{
throw new ArgumentOutOfRangeException($"The end {end} of the slice must be greater than the start {start}.");
}
else if (end - start > Int32.MaxValue)
{
throw new ArgumentOutOfRangeException($"The size of the slice must be less than or equal to {Int32.MaxValue}.");
}
_GetSegment(end, out void* ptr, out int offset);
void* p = BufferHelpers.Add<T>(new IntPtr(ptr), offset).ToPointer();
return new Span<T>(p, (int) (end - start));
}
public unsafe Vector<T> GetAsSingleVector()
{
ThrowIfNotAllocatedOrInvalid();
if (this.Length != (ulong) VectorLength)
{
throw new InvalidOperationException($"The length of the array must be {Vector<T>.Count} elements to create a vector of type {CLRType.Name}.");
}
return Unsafe.Read<Vector<T>>(handle.ToPointer());
}
public unsafe Span<Vector<T>> GetSliceSegmentAsVectorSpan(ulong index)
{
ThrowIfNotAllocatedOrInvalid();
if ((Length - index) < (ulong) VectorLength)
{
ThrowIfIndexOutOfRange(index);
}
T v = this[index];
int i = _GetSegmentIndex(index);
if (segments2[i].Item2 % VectorLength != 0)
{
BufferIsNotVectorisable();
}
return new Span<Vector<T>>(segments2[i].Item1.ToPointer(), segments2[i].Item2 / VectorLength + 1);
}
public unsafe Vector<T> GetSliceAsSingleVector(ulong index)
{
ThrowIfNotAllocatedOrInvalid();
ThrowIfIndexOutOfRange(index);
if ((Length - index) < (ulong) VectorLength)
{
BufferIsNotVectorisable();
}
int i = _GetSegmentIndex(index);
_GetSegment(index, out void* ptr, out int offset);
IntPtr start = BufferHelpers.Add<T>(segments2[i].Item1, offset);
return Unsafe.Read<Vector<T>>(start.ToPointer());
}
#endregion
#region Vector
/*
public unsafe void VectorMultiply(T value)
{
ThrowIfNotAllocatedOrInvalid();
ThrowIfNotNumeric();
Vector<T> mul = new Vector<T>(value);
for (int h = 0; h < segments2.Length; h++)
{
int i = 0;
for (; i < segments2[h].Item2 - VectorLength; i++ )
{
Vector<T> v = Unsafe.Read<Vector<T>>(BufferHelpers.Add<T>(segments2[h].Item1, i).ToPointer());
v = v * mul;
}
f
}
}*/
#endregion
#region Helpers
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[DebuggerStepThrough]
private void ThrowIfCannotAcquire()
{
if (!Acquire())
{
throw new InvalidOperationException("Could not acquire handle.");
}
}
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[DebuggerStepThrough]
private void ThrowIfIndexOutOfRange(ulong index)
{
if (index >= Length)
{
BufferIndexIsOutOfRange(index);
}
}
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[DebuggerStepThrough]
private void ThrowIfNotAllocatedOrInvalid()
{
if (IsNotAllocated)
{
BufferIsNotAllocated();
}
else if (IsInvalid)
{
HandleIsInvalid();
}
}
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[DebuggerStepThrough]
private void ThrowIfRetained()
{
if (IsRetained)
{
throw new InvalidOperationException($"SafeBuffer<{typeof(T)}[{Length}] has outstanding references.");
}
}
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[DebuggerStepThrough]
private void ThrowIfNotAllocated()
{
if (IsNotAllocated)
{
BufferIsNotAllocated();
}
}
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[DebuggerStepThrough]
private void ThrowIfNotVectorisable()
{
if (!IsVectorizable)
{
BufferIsNotVectorisable();
}
}
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[DebuggerStepThrough]
private void ThrowIfNotNumeric()
{
if (!IsNumeric)
{
BufferIsNotNumeric();
}
}
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[DebuggerStepThrough]
private static InvalidOperationException HandleIsInvalid()
{
Contract.Assert(false, "The handle is invalid.");
return new InvalidOperationException("The handle is invalid.");
}
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[DebuggerStepThrough]
private static InvalidOperationException BufferIsNotAllocated()
{
Contract.Assert(false, "Unallocated safe buffer used.");
return new InvalidOperationException("Unallocated safe buffer used.");
}
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[DebuggerStepThrough]
private static InvalidOperationException BufferIsNotVectorisable()
{
Contract.Assert(false, "Buffer is not vectorisable.");
return new InvalidOperationException("Buffer is not vectorisable.");
}
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[DebuggerStepThrough]
private static InvalidOperationException BufferIsNotNumeric()
{
Contract.Assert(false, "Buffer is not numeric.");
return new InvalidOperationException("Buffer is not numeric.");
}
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[DebuggerStepThrough]
private void BufferIndexIsOutOfRange(ulong index)
{
Contract.Assert(false, $"Index {index} into buffer is out of range.");
throw new IndexOutOfRangeException($"Index {index} into buffer is out of range.");
}
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[DebuggerStepThrough]
private void BufferSizeIsOutOfRange(ulong index)
{
Contract.Assert(false, $"Size {index} exceeds the size of the buffer.");
throw new IndexOutOfRangeException($"Size {index} exceeds the size of the buffer.");
}
#endregion
#endregion
#region Operators
public ref T this[ulong index]
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => ref _Read(index);
}
#endregion
#region Fields
protected static readonly Type CLRType = typeof(T);
protected static readonly T Element = default;
protected static readonly uint ElementSizeInBytes = (uint) JemUtil.SizeOfStruct<T>();
protected static readonly UInt64 NotAllocated = UInt64.MaxValue;
protected static readonly bool IsNumeric = JemUtil.IsNumericType<T>();
protected static readonly int VectorLength = Vector<T>.Count;
protected static bool SIMD = Vector.IsHardwareAccelerated;
protected internal unsafe void* voidPtr;
protected unsafe IntPtr[] segments;
protected unsafe Tuple<IntPtr, int>[] segments2;
//Debugger Display = {T[length]}
private string DebuggerDisplay => string.Format("{{{0}[{1}]}}", typeof(T).Name, Length);
#endregion
}
}
================================================
FILE: jemalloc.Api/HugeBufferEnumerator.cs
================================================
using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Text;
namespace jemalloc
{
/// <summary>Enumerates the elements of a <see cref="HugeBuffer{T}"/>.</summary>
public class HugeBufferEnumerator<T> : IEnumerator, IEnumerator<T> where T : struct, IEquatable<T>
{
/// <summary>The span being enumerated.</summary>
private readonly HugeBuffer<T> _buffer;
/// <summary>The next index to yield.</summary>
private ulong _index;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal HugeBufferEnumerator(HugeBuffer<T> buffer)
{
_buffer = buffer;
_buffer.Acquire();
_index = UInt64.MaxValue;
}
/// <summary>Advances the enumerator to the next element of the buffer.</summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool MoveNext()
{
if (_index == UInt64.MaxValue)
{
_index = 0;
return true;
}
else
{
ulong index = _index + 1;
if (index < _buffer.Length)
{
_index = index;
return true;
}
else
{
return false;
}
}
}
public void Reset()
{
_index = UInt64.MaxValue;
}
/// <summary>Gets the element at the current position of the enumerator.</summary>
object IEnumerator.Current
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _buffer[_index];
}
public T Current
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _buffer[_index];
}
void IDisposable.Dispose()
{
_buffer.Release();
}
}
}
================================================
FILE: jemalloc.Api/IBufferAllocation.cs
================================================
using System;
using System.Collections.Generic;
using System.Text;
namespace jemalloc
{
public interface IBufferAllocation
{
IntPtr Ptr { get; }
ulong Size { get; }
long TimeStamp { get; }
int ThreadId { get; }
int HashCode { get; }
}
}
================================================
FILE: jemalloc.Api/JemApi.cs
================================================
using System;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Collections.Immutable;
using System.Linq;
using System.IO;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
using System.Runtime.ConstrainedExecution;
using System.Security;
using System.Text;
using System.Threading;
namespace jemalloc
{
#region Types and Enums
public class CallerInformation
{
public string Name;
public string File;
public int LineNumber;
public CallerInformation(string name, string file, int line_number)
{
this.Name = name;
this.File = file;
this.LineNumber = line_number;
}
public override string ToString() => Jem.GetCallerDetails(this);
}
internal enum ERRNO
{
ENONE = 0,
EPERM = 1,
ENOENT = 2,
ESRCH = 3,
EINTR = 4,
EIO = 5,
ENXIO = 6,
E2BIG = 7,
ENOEXEC = 8,
EBADF = 9,
ECHILD = 10,
EAGAIN = 11,
ENOMEM = 12,
EACCES = 13,
EFAULT = 14,
EBUSY = 16,
EEXIST = 17,
EXDEV = 18,
ENODEV = 19,
ENOTDIR = 20,
EISDIR = 21,
ENFILE = 23,
EMFILE = 24,
ENOTTY = 25,
EFBIG = 27,
ENOSPC = 28,
ESPIPE = 29,
EROFS = 30,
EMLINK = 31,
EPIPE = 32,
EDOM = 33,
EDEADLK = 36,
ENAMETOOLONG = 38,
ENOLCK = 39,
ENOSYS = 40,
ENOTEMPTY = 41
}
[Flags]
public enum ALLOC_FLAGS
{
ZERO,
DETAILS
}
#endregion
public unsafe static partial class Jem
{
#region Constructor
static Jem()
{
__Internal.JeMallocMessage += messagesCallback;
}
#endregion
#region Methods
#region Low-level jemalloc API
public static global::System.IntPtr Malloc(ulong size, [CallerMemberName] string memberName = "", [CallerFilePath] string fileName = "", [CallerLineNumber] int lineNumber = 0)
{
CallerInformation caller = new CallerInformation(memberName, fileName, lineNumber);
Initialized = true;
IntPtr __ret = __Internal.JeMalloc(size);
if (__ret != IntPtr.Zero)
{
allocLock.EnterWriteLock();
_Allocations.Add(__ret, 0);
allocLock.ExitWriteLock();
return __ret;
}
else
{
throw new OutOfMemoryException($"Could not allocate {size} bytes for {GetCallerDetails(caller)}.");
}
}
public static global::System.IntPtr Calloc(ulong num, ulong size, [CallerMemberName] string memberName = "", [CallerFilePath] string fileName = "", [CallerLineNumber] int lineNumber = 0)
{
CallerInformation caller = new CallerInformation(memberName, fileName, lineNumber);
Initialized = true;
IntPtr __ret = __Internal.JeCalloc(num, size);
if (__ret != IntPtr.Zero)
{
allocLock.EnterWriteLock();
_Allocations.Add(__ret, 0);
allocLock.ExitWriteLock();
return __ret;
}
else
{
throw new OutOfMemoryException($"Could not allocate {num * size} bytes for {GetCallerDetails(caller)}.");
}
}
public static int PosixMemalign(void** memptr, ulong alignment, ulong size)
{
Initialized = true;
var __ret = __Internal.JePosixMemalign(memptr, alignment, size);
return __ret;
}
public static global::System.IntPtr AlignedAlloc(ulong alignment, ulong size)
{
Initialized = true;
var __ret = __Internal.JeAlignedAlloc(alignment, size);
return __ret;
}
public static global::System.IntPtr Realloc(global::System.IntPtr ptr, ulong size)
{
Initialized = true;
var __ret = __Internal.JeRealloc(ptr, size);
return __ret;
}
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
public static bool Free(global::System.IntPtr ptr, [CallerMemberName] string memberName = "", [CallerFilePath] string fileName = "", [CallerLineNumber] int lineNumber = 0)
{
bool ret = false;
RuntimeHelpers.PrepareConstrainedRegions();
try
{
}
finally
{
allocLock.EnterUpgradeableReadLock();
ret = _Allocations.ContainsKey(ptr);
if (ret)
{
allocLock.EnterWriteLock();
_Allocations.Remove(ptr);
__Internal.JeFree(ptr);
allocLock.ExitWriteLock();
}
allocLock.ExitUpgradeableReadLock();
}
return ret;
}
public static global::System.IntPtr Mallocx(ulong size, int flags)
{
Initialized = true;
var __ret = __Internal.JeMallocx(size, flags);
return __ret;
}
public static global::System.IntPtr Rallocx(global::System.IntPtr ptr, ulong size, int flags)
{
Initialized = true;
var __ret = __Internal.JeRallocx(ptr, size, flags);
return __ret;
}
public static ulong Xallocx(global::System.IntPtr ptr, ulong size, ulong extra, int flags)
{
Initialized = true;
var __ret = __Internal.JeXallocx(ptr, size, extra, flags);
return __ret;
}
public static ulong Sallocx(global::System.IntPtr ptr, int flags)
{
Initialized = true;
var __ret = __Internal.JeSallocx(ptr, flags);
return __ret;
}
public static void Dallocx(global::System.IntPtr ptr, int flags)
{
Initialized = true;
__Internal.JeDallocx(ptr, flags);
}
public static void Sdallocx(global::System.IntPtr ptr, ulong size, int flags)
{
Initialized = true;
__Internal.JeSdallocx(ptr, size, flags);
}
public static ulong Nallocx(ulong size, int flags)
{
Initialized = true;
var __ret = __Internal.JeNallocx(size, flags);
return __ret;
}
public static int Mallctl(string name, global::System.IntPtr oldp, ref ulong oldlenp, global::System.IntPtr newp, ulong newlen)
{
fixed (ulong* __refParamPtr2 = &oldlenp)
{
var __arg2 = __refParamPtr2;
var __ret = __Internal.JeMallctl(name, oldp, __arg2, newp, newlen);
return __ret;
}
}
public static int Mallctlnametomib(string name, ref ulong mibp, ref ulong miblenp)
{
fixed (ulong* __refParamPtr1 = &mibp)
{
var __arg1 = __refParamPtr1;
fixed (ulong* __refParamPtr2 = &miblenp)
{
var __arg2 = __refParamPtr2;
var __ret = __Internal.JeMallctlnametomib(name, __arg1, __arg2);
return __ret;
}
}
}
public static int Mallctlbymib(ref ulong mib, ulong miblen, global::System.IntPtr oldp, ref ulong oldlenp, global::System.IntPtr newp, ulong newlen)
{
fixed (ulong* __refParamPtr0 = &mib)
{
var __arg0 = __refParamPtr0;
fixed (ulong* __refParamPtr3 = &oldlenp)
{
var __arg3 = __refParamPtr3;
var __ret = __Internal.JeMallctlbymib(__arg0, miblen, oldp, __arg3, newp, newlen);
return __ret;
}
}
}
#endregion
#region High-level API
public static bool Init(string conf)
{
if (!Initialized)
{
if (mallocMessagesBuilder == null)
{
mallocMessagesBuilder = new StringBuilder();
}
try
{
MallocConf = conf;
}
catch (Exception)
{
throw new ArgumentException($"The configuration string \'{conf}\' is invalid");
}
Initialized = true;
return true;
}
else return false;
}
#region Memory life-time management
public static int GetRefCount(IntPtr ptr)
{
allocLock.EnterReadLock();
int c = _Allocations[ptr];
allocLock.ExitReadLock();
return c;
}
public static void IncrementRefCount(IntPtr ptr)
{
allocLock.EnterWriteLock();
_Allocations[ptr] = _Allocations[ptr] + 1;
allocLock.ExitWriteLock();
}
public static void DecrementRefCount(IntPtr ptr)
{
allocLock.EnterWriteLock();
_Allocations[ptr] = _Allocations[ptr] - 1;
allocLock.ExitWriteLock();
}
public static bool PtrIsAllocated(IntPtr ptr)
{
allocLock.EnterReadLock();
bool r = _Allocations.ContainsKey(ptr);
allocLock.ExitReadLock();
return r;
}
#endregion
public static string MallocStats => GetMallocStats(string.Empty);
public static string GetMallocStats(string opt)
{
StringBuilder statsBuilder = new StringBuilder(1000);
__Internal.JeMallocMessageCallback stats = (o, m) => { statsBuilder.Append(m); };
__Internal.JeMallocStatsPrint(Marshal.GetFunctionPointerForDelegate(stats), IntPtr.Zero, opt);
if (Environment.OSVersion.Platform == PlatformID.Win32NT)
{
statsBuilder = statsBuilder.Replace("\\n", "\\r\\n");
}
return statsBuilder.ToString();
}
public static ulong MallocUsableSize(global::System.IntPtr ptr)
{
var __ret = __Internal.JeMallocUsableSize(ptr);
return __ret;
}
public static string MallocConf
{
get
{
return Marshal.PtrToStringAnsi(__Internal.JeGetMallocConf());
}
set
{
__Internal.JeSetMallocConf(Marshal.StringToHGlobalAnsi(value));
}
}
#region MallCtl
public static int GetMallCtlInt32(string name)
{
void* i = stackalloc int[1];
ulong size = sizeof(Int32);
ERRNO r = (ERRNO) Mallctl(name, (IntPtr) i, ref size, IntPtr.Zero, 0);
return r == ERRNO.ENONE ? *(Int32*)(i) : throw GetExceptionForErrNo($"Could not get mallctl value {name}.", r);
}
public static bool SetMallCtlInt32(string name, int value)
{
void* i = &value;
ulong size = sizeof(Int32);
ERRNO r = (ERRNO) Mallctl(name, IntPtr.Zero, ref size, (IntPtr) i, size);
return r == ERRNO.ENONE ? true : throw GetExceptionForErrNo($"Could not set mallctl value {name} to {value}.", r);
}
public static bool GetMallCtlBool(string name)
{
void* i = stackalloc byte[1];
ulong size = sizeof(byte);
ERRNO r = (ERRNO)Mallctl(name, (IntPtr)i, ref size, IntPtr.Zero, 0);
return r == ERRNO.ENONE ? *(byte*)(i) == 1 ? true : false:
r == ERRNO.ENOENT ? false : throw GetExceptionForErrNo($"Could not get mallctl value {name}.", r);
}
public static bool SetMallCtlBool(string name, bool value)
{
byte v = value ? (byte) 1 : (byte) 0;
void* n = &v;
ulong size = sizeof(byte);
ERRNO r = (ERRNO)Mallctl(name, IntPtr.Zero, ref size, (IntPtr)n, size);
return r == ERRNO.ENONE ? true : throw GetExceptionForErrNo($"Could not set mallctl value {name} to {value}.", r);
}
public static UInt64 GetMallCtlUInt64(string name)
{
void* i = stackalloc UInt64[1];
ulong size = sizeof(UInt64);
ERRNO r = (ERRNO) Mallctl(name, (IntPtr) i, ref size, IntPtr.Zero, 0);
return r == ERRNO.ENONE ? *(UInt64*)(i) : throw GetExceptionForErrNo($"Could not get mallctl value {name}.", r);
}
public static bool SetMallCtlUInt64(string name, ulong value)
{
void* n = &value;
ulong size = sizeof(UInt64);
ERRNO r = (ERRNO) Mallctl(name, IntPtr.Zero, ref size, (IntPtr) n, size);
return r == ERRNO.ENONE ? true : throw GetExceptionForErrNo($"Could not set mallctl value {name} to {value}.", r);
}
public static Int64 GetMallCtlSInt64(string name)
{
void* i = stackalloc Int64[1];
ulong size = sizeof(Int64);
ERRNO r = (ERRNO) Mallctl(name, (IntPtr) i, ref size, IntPtr.Zero, 0);
return r == ERRNO.ENONE ? *(Int64*)(i) : throw GetExceptionForErrNo($"Could not get mallctl value {name}.", r);
}
public static bool SetMallCtlSInt64(string name, long value)
{
void* n = &value;
ulong size = sizeof(Int64);
ERRNO r = (ERRNO) Mallctl(name, IntPtr.Zero, ref size, (IntPtr)n, size);
return r == ERRNO.ENONE ? true : throw GetExceptionForErrNo($"Could not set mallctl value {name} to {value}.", r);
}
public static string GetMallCtlStr(string name)
{
void* p = stackalloc IntPtr[1];
IntPtr retp = new IntPtr(p);
ulong size = (ulong)sizeof(IntPtr);
int ret = Mallctl(name, (IntPtr) p, ref size, IntPtr.Zero, 0);
if ((ERRNO)ret == ERRNO.ENONE)
{
return Marshal.PtrToStringAnsi(*(IntPtr*)p);
}
else
{
throw GetExceptionForErrNo($"Could not get mallctl value {name}.", (ERRNO)ret);
}
}
#endregion
public static int TryFreeAll()
{
allocLock.EnterWriteLock();
int c = _Allocations.Count;
foreach (IntPtr p in _Allocations.Keys)
{
Jem.Free(p);
_Allocations.Remove(p);
}
allocLock.ExitWriteLock();
return c;
}
public static Span<T> Malloc<T>(ulong size, int length, [CallerMemberName] string memberName = "", [CallerFilePath] string fileName = "", [CallerLineNumber] int lineNumber = 0) where T : struct
{
IntPtr ptr = Malloc(size, memberName, fileName, lineNumber);
return new Span<T>((void*)ptr, length);
}
#region FixedBuffer
public static IntPtr AllocateFixedBuffer<T>(ulong length, ulong size, long timestamp, int tid, int rid, [CallerMemberName] string memberName = "", [CallerFilePath] string fileName = "", [CallerLineNumber] int lineNumber = 0)
{
IntPtr ptr = Jem.Calloc(length, size, memberName, fileName, lineNumber);
if (ptr != IntPtr.Zero)
{
fixedBufferLock.EnterWriteLock();
_FixedBufferAllocations.Add(ptr, new FixedBufferAllocation(ptr, length * size, timestamp, tid, rid));
fixedBufferLock.ExitWriteLock();
}
return ptr;
}
public static bool FreeFixedBuffer(IntPtr ptr)
{
fixedBufferLock.EnterWriteLock();
bool r = _FixedBufferAllocations.Remove(ptr);
fixedBufferLock.ExitWriteLock();
if (!r)
{
return false;
}
else
{
Jem.Free(ptr);
return true;
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool FixedBufferIsAllocatedWith(IntPtr ptr, ulong size, long timestamp, int tid, int rid)
{
fixedBufferLock.EnterReadLock();
bool r1 = _FixedBufferAllocations.ContainsKey(ptr);
if (!r1)
{
fixedBufferLock.ExitReadLock();
return false;
}
else
{
bool r2 = _FixedBufferAllocations[ptr].Equals(new FixedBufferAllocation(ptr, size, timestamp, tid, rid));
fixedBufferLock.ExitReadLock();
return r2;
}
}
#endregion
#endregion
#region Utility methods
internal static bool AllocFlagSet(ALLOC_FLAGS flag)
{
return (flag & Flags) == flag;
}
internal static Exception GetExceptionForErrNo(string message, ERRNO no)
{
switch (no)
{
case ERRNO.ENOMEM:
return new OutOfMemoryException(message);
default:
return new Exception(message + $" {no}.");
}
}
internal static string GetCallerDetails(string memberName, string fileName, int lineNumber)
{
return $"Member {memberName} at line {lineNumber} in file {fileName}";
}
internal static string GetCallerDetails(CallerInformation c)
{
return $"Member {c.Name} at line {c.LineNumber} in file {c.File}";
}
#endregion
#endregion
#region Properties
public static bool Initialized { get; private set; } = false;
public static ALLOC_FLAGS Flags;
#region Malloc Messages
public static event JeMallocMessageAction MallocMessage;
public static string MallocMessages => mallocMessagesBuilder.ToString();
private static __Internal.JeMallocMessageCallback messagesCallback = (o, m) =>
{
mallocMessagesBuilder.Append(m);
MallocMessage.Invoke(m);
};
#endregion
#region jemalloc Statistics
public static UInt64 AllocatedBytes => GetMallCtlUInt64("stats.allocated");
public static UInt64 ActiveBytes => GetMallCtlUInt64("stats.active");
public static UInt64 MappedBytes => GetMallCtlUInt64("stats.mapped");
public static UInt64 ResidentBytes => GetMallCtlUInt64("stats.resident");
#endregion
#region Allocations ledgers
public static List<Tuple<IntPtr, ulong, CallerInformation>> AllocationsDetails { get; private set; } = new List<Tuple<IntPtr, ulong, CallerInformation>>();
#endregion
#endregion
#region Fields
private static StringBuilder mallocMessagesBuilder = new StringBuilder();
private static Dictionary<IntPtr, int> _Allocations = new Dictionary<IntPtr, int>(1024);
private static Dictionary<IntPtr, FixedBufferAllocation> _FixedBufferAllocations = new Dictionary<IntPtr, FixedBufferAllocation>(1024);
private static FixedBufferComparator fixedBufferComparator = new FixedBufferComparator();
private static ReaderWriterLockSlim allocLock = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion);
private static ReaderWriterLockSlim fixedBufferLock = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion);
#endregion
}
}
================================================
FILE: jemalloc.Api/JemPinnable.cs
================================================
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.Text;
namespace jemalloc
{
[StructLayout(LayoutKind.Sequential)]
internal sealed class JemPinnable<T>
{
public T Data;
}
}
================================================
FILE: jemalloc.Api/JemUtil.cs
================================================
using System;
using System.Diagnostics;
using System.Collections.Generic;
using System.Collections.Concurrent;
using System.Collections.Immutable;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.ConstrainedExecution;
using System.Security;
namespace jemalloc
{
public static class JemUtil
{
#region Constructor
static JemUtil()
{
}
#endregion
#region Properties
public static ConcurrentDictionary<string, object> BenchmarkValues { get; } = new ConcurrentDictionary<string, object>();
public static ConcurrentDictionary<string, string> BenchmarkStatistics { get; } = new ConcurrentDictionary<string, string>();
public static Process CurrentProcess { get; } = Process.GetCurrentProcess();
public static Random Rng { get; } = new Random();
public static long ProcessPrivateMemory
{
get
{
CurrentProcess.Refresh();
return CurrentProcess.PrivateMemorySize64;
}
}
public static long ProcessPeakVirtualMem
{
get
{
CurrentProcess.Refresh();
return CurrentProcess.PeakVirtualMemorySize64;
}
}
public static long ProcessPeakWorkingSet
{
get
{
CurrentProcess.Refresh();
return CurrentProcess.PeakWorkingSet64;
}
}
public static long ProcessPeakPagedMem
{
get
{
CurrentProcess.Refresh();
return CurrentProcess.PeakPagedMemorySize64;
}
}
public static long ProcessVirtualMemory
{
get
{
CurrentProcess.Refresh();
return CurrentProcess.VirtualMemorySize64;
}
}
public static long ProcessWorkingSet
{
get
{
CurrentProcess.Refresh();
return CurrentProcess.WorkingSet64;
}
}
public static long ProcessPagedMemory
{
get
{
CurrentProcess.Refresh();
return CurrentProcess.PagedMemorySize64;
}
}
public static Type CLRType<T>() => typeof(T);
public static uint ElementSizeInBytes<T>() where T: struct => (uint)JemUtil.SizeOfStruct<T>();
public static int VectorLength<T> () where T : struct => Vector<T>.Count;
public static bool SIMD => Vector.IsHardwareAccelerated;
#endregion
#region Methods
public static bool IsNumericType<T>()
{
return NumericTypes.Contains(typeof(T));
}
public unsafe static Span<T> PtrToSpan<T>(IntPtr ptr, int length)
{
return new Span<T>((void*)ptr, length);
}
public unsafe static ref readonly T PtrToStruct<T>(void* ptr) where T : struct
{
return ref Unsafe.AsRef<T>(ptr);
}
public unsafe static TReturn ValToGenericStruct<TValue, TReturn>(TValue v) where TValue : struct where TReturn : struct
{
void* ptr = Unsafe.AsPointer(ref v);
return PtrToStruct<TReturn>(ptr);
}
public static int SizeOfStruct<T>() where T : struct
{
return Unsafe.SizeOf<T>();
}
// System.String.GetHashCode(): http://referencesource.microsoft.com/#mscorlib/system/string.cs,0a17bbac4851d0d4
// System.Web.Util.StringUtil.GetStringHashCode(System.String): http://referencesource.microsoft.com/#System.Web/Util/StringUtil.cs,c97063570b4e791a
public static int CombineHashCodes(params int[] hashCodes)
{
int hash1 = (5381 << 16) + 5381;
int hash2 = hash1;
int i = 0;
foreach (var hashCode in hashCodes)
{
if (i % 2 == 0)
hash1 = ((hash1 << 5) + hash1 + (hash1 >> 27)) ^ hashCode;
else
hash2 = ((hash2 << 5) + hash2 + (hash2 >> 27)) ^ hashCode;
++i;
}
return hash1 + (hash2 * 1566083941);
}
public static string PrintSize(double bytes, string suffix = "")
{
if (bytes >= 0 && bytes <= 1024)
{
return string.Format("{0:N0} {1}", bytes, suffix);
}
else if (bytes >= 1024 && bytes < (1024 * 1024))
{
return string.Format("{0:N1} K{1}", bytes / 1024, suffix);
}
else if (bytes >= (1024 * 1024) && bytes < (1024 * 1024 * 1024))
{
return string.Format("{0:N1} M{1}", bytes / (1024 * 1024), suffix);
}
else if (bytes >= (1024 * 1024 * 1024) && (bytes < (1024f * 1024f * 1024f * 1024f)))
{
return string.Format("{0:N1} G{1}", bytes / (1024 * 1024 * 1024), suffix);
}
else if (bytes >= (1024f * 1024f * 1024f * 1024f) && (bytes < (1024f * 1024f * 1024f * 1024f * 1024f)))
{
return string.Format("{0:N1} T{1}", bytes / (1024f * 1024f * 1024f * 1024f), suffix);
}
else throw new ArgumentOutOfRangeException();
}
public static string PrintBytes(double bytes, string suffix = "")
{
if (bytes >= 0 && bytes <= 1024)
{
return string.Format("{0:N0} B{1}", bytes, suffix);
}
else if (bytes >= 1024 && bytes < (1024 * 1024))
{
return string.Format("{0:N1} KB{1}", bytes / 1024, suffix);
}
else if (bytes >= (1024 * 1024) && bytes < (1024 * 1024 * 1024))
{
return string.Format("{0:N1} MB{1}", bytes / (1024 * 1024), suffix);
}
else if (bytes >= (1024 * 1024 * 1024) && (bytes < (1024f * 1024f * 1024f * 1024f)))
{
return string.Format("{0:N1} GB{1}", bytes / (1024 * 1024 * 1024), suffix);
}
else if (bytes >= (1024f * 1024f * 1024f * 1024f) && (bytes < (1024f * 1024f * 1024f * 1024f * 1024f)))
{
return string.Format("{0:N1} TB{1}", bytes / (1024f * 1024f * 1024f * 1024f), suffix);
}
else throw new ArgumentOutOfRangeException();
}
public static Tuple<double, string> PrintBytesToTuple(double bytes, string suffix = "")
{
string[] s = PrintBytes(bytes, suffix).Split(' ');
return new Tuple<double, string>(Double.Parse(s[0]), s[1]);
}
public unsafe static ulong GetCurrentThreadCycles()
{
if (Environment.OSVersion.Platform != PlatformID.Win32NT)
{
throw new PlatformNotSupportedException();
}
if (!__Internal.DuplicateHandle(__Internal.GetCurrentProcess(), __Internal.GetCurrentThread(), __Internal.GetCurrentProcess(), out IntPtr* p,
0x0400, true, (uint) __Internal.DuplicateOptions.DUPLICATE_SAME_ACCESS))
{
throw new System.ComponentModel.Win32Exception();
}
if (__Internal.QueryThreadCycleTime(in *p, out ulong cycles))
{
//__Internal.CloseHandle(*p);
return cycles;
}
else
{
//__Internal.CloseHandle(*p);
throw new System.ComponentModel.Win32Exception();
}
}
public partial struct __Internal
{
[Flags]
public enum DuplicateOptions : uint
{
DUPLICATE_CLOSE_SOURCE = (0x00000001),// Closes the source handle. This occurs regardless of any error status returned.
DUPLICATE_SAME_ACCESS = (0x00000002), //Ignores the dwDesiredAccess parameter. The duplicate handle has the same access as the source handle.
}
[DllImport("kernel32.dll", SetLastError = true)]
[SuppressUnmanagedCodeSecurity]
internal static extern bool QueryThreadCycleTime(in IntPtr hThread, out ulong cycles);
[DllImport("kernel32.dll", SetLastError = true)]
[SuppressUnmanagedCodeSecurity]
internal static extern IntPtr GetCurrentThread();
[DllImport("kernel32.dll", SetLastError = true)]
[SuppressUnmanagedCodeSecurity]
internal static extern IntPtr GetCurrentProcess();
[DllImport("kernel32.dll", SetLastError = true)]
[SuppressUnmanagedCodeSecurity]
[return: MarshalAs(UnmanagedType.Bool)]
internal static unsafe extern bool DuplicateHandle(IntPtr hSourceProcessHandle,IntPtr hSourceHandle, IntPtr hTargetProcessHandle, out IntPtr* lpTargetHandle, uint dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, uint dwOptions);
[DllImport("kernel32.dll", SetLastError = true)]
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[SuppressUnmanagedCodeSecurity]
[return: MarshalAs(UnmanagedType.Bool)]
internal static extern bool CloseHandle(IntPtr hObject);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool QueryPerformanceCounter(out long lpPerformanceCount);
}
#endregion
#region Fields
public static readonly Type Int8CLRType = typeof(SByte);
public static readonly Type UInt8CLRType = typeof(Byte);
public static readonly Type Int16CLRType = typeof(Int16);
public static readonly Type UInt16CLRType = typeof(UInt16);
public static readonly Type Int32CLRType = typeof(Int32);
public static readonly Type UInt32CLRType = typeof(UInt32);
public static readonly Type Int64CLRType = typeof(Int64);
public static readonly Type UInt64CLRType = typeof(UInt64);
public static readonly Type SingleCLRType = typeof(Single);
public static readonly Type DoubleCLRType = typeof(Double);
public static readonly Type CharCLRType = typeof(Char);
public static readonly Type DecimalCLRType = typeof(Decimal);
public static readonly Type IntPtrCLRType = typeof(IntPtr);
public static readonly Type BoolCLRType = typeof(Boolean);
public static readonly HashSet<Type> NumericTypes = new HashSet<Type>(new Type[]
{
Int8CLRType, UInt8CLRType, Int16CLRType, UInt16CLRType, Int32CLRType, UInt32CLRType, Int64CLRType, UInt64CLRType,
SingleCLRType, DoubleCLRType, CharCLRType, BoolCLRType
});
#endregion
}
}
================================================
FILE: jemalloc.Api/MemoryRef.cs
================================================
using System;
using System.Collections.Generic;
using System.Buffers;
using System.Text;
namespace jemalloc
{
public readonly ref struct MemoryRef<T> where T : struct
{
internal MemoryRef(Guid guid, MemoryHandle h)
{
Id = guid;
Handle = h;
}
private readonly Guid Id;
private readonly MemoryHandle Handle;
public bool Release()
{
return false;
}
}
}
================================================
FILE: jemalloc.Api/NDArray.cs
================================================
using System;
using System.Collections.Generic;
using System.Text;
namespace jemalloc
{
//WIP
public class NDArray<T> where T : struct
{
public NDArray(ulong points, int rank)
{
//data[3L]
}
//HugeArray<T>[] data;
}
}
================================================
FILE: jemalloc.Api/SafeArray.cs
================================================
using System;
using System.Collections.Generic;
using System.Numerics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
namespace jemalloc
{
public class SafeArray<T> : SafeBuffer<T> where T : struct, IEquatable<T>
{
public SafeArray(int length, params T[] values) : base(length, values) {}
}
}
================================================
FILE: jemalloc.Api/SafeBuffer.cs
================================================
using System;
using System.Buffers;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.Contracts;
using System.Numerics;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;
using System.Runtime.ConstrainedExecution;
using System.Text;
namespace jemalloc
{
public abstract class SafeBuffer<T> : SafeHandle, IRetainable, IDisposable, IEquatable<SafeBuffer<T>>, IEnumerable<T> where T : struct, IEquatable<T>
{
#region Constructors
protected SafeBuffer(int length, params T[] values) : base(IntPtr.Zero, true)
{
if (BufferHelpers.IsReferenceOrContainsReferences(typeof(T), out FieldInfo field))
{
throw new ArgumentException($"Only structures without reference fields can be used with this class. The field {field.Name} has type {field.FieldType.Name}.");
}
if (values.Length > length)
{
throw new ArgumentException("The length of the list of values must be smaller or equal to the length of the buffer");
}
SizeInBytes = NotAllocated;
base.SetHandle(Allocate(length));
if (IsAllocated)
{
CopyFrom(values);
}
}
#endregion
#region Overriden members
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
protected override bool ReleaseHandle()
{
bool r = Jem.Free(handle);
if (!r)
{
return false;
}
else
{
handle = IntPtr.Zero;
unsafe
{
voidPtr = (void *) 0;
}
Length = 0;
SizeInBytes = 0;
return true;
}
}
public override bool IsInvalid => handle == IntPtr.Zero;
#region Disposer
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
protected override void Dispose(bool disposing)
{
if (disposing)
{
ThrowIfNotAllocatedOrInvalid();
ThrowIfRetained();
ReleaseHandle();
}
base.Dispose(disposing);
}
#endregion
#endregion
#region Implemented members
public void Retain() => Acquire();
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
public bool Release()
{
if (IsNotAllocated || IsInvalid)
{
return false;
}
else
{
Jem.DecrementRefCount(handle);
DangerousRelease();
return true;
}
}
public bool Equals(SafeBuffer<T> other)
{
ThrowIfNotAllocatedOrInvalid();
return this.handle == other.handle && this.Length == other.Length;
}
public IEnumerator<T> GetEnumerator() => new SafeBufferEnumerator<T>(this);
IEnumerator IEnumerable.GetEnumerator() => new SafeBufferEnumerator<T>(this);
#endregion
#region Properties
public int Length { get; protected set; }
public ulong SizeInBytes { get; protected set; }
public bool IsNotAllocated => SizeInBytes == NotAllocated;
public bool IsAllocated => !IsNotAllocated;
public bool IsValid => !IsInvalid;
public bool IsRetained => IsValid ? _RefCount > 0 : false;
public bool IsVectorizable { get; protected set; }
public Span<T> Span
{
get
{
ThrowIfNotAllocatedOrInvalid();
return _Span;
}
}
protected int _RefCount => Jem.GetRefCount(handle);
protected unsafe Span<T> _Span => new Span<T>(voidPtr, Length);
#endregion
#region Methods
#region Memory management
protected unsafe virtual IntPtr Allocate(int length)
{
if (length <= 0)
throw new ArgumentOutOfRangeException("length");
Contract.EndContractBlock();
ulong s = checked((uint)length * ElementSizeInBytes);
handle = Jem.Calloc((uint)length, ElementSizeInBytes);
if (handle != IntPtr.Zero)
{
voidPtr = handle.ToPointer();
Length = length;
SizeInBytes = s;
InitVector();
}
return handle;
}
protected void InitVector()
{
if (IsNumeric && Length % VectorLength == 0 && SIMD && IsNumeric)
{
IsVectorizable = true;
}
else
{
IsVectorizable = false;
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
protected unsafe ref T Read(int index)
{
// return (T*) (_ptr + byteOffset);
return ref Unsafe.Add(ref Unsafe.AsRef<T>(voidPtr), index);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
protected unsafe void Write(int index, T value)
{
ref T v = ref Unsafe.Add(ref Unsafe.AsRef<T>(voidPtr), index);
v = value;
}
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
public bool Acquire()
{
if (IsNotAllocated || IsInvalid)
return false;
bool success = false;
DangerousAddRef(ref success);
if (success)
{
Jem.IncrementRefCount(handle);
}
return success;
}
public bool Release(int n)
{
bool r = false;
for (int i = 0; i < n; i++)
{
r = Release();
if (r)
{
continue;
}
else
{
return r;
}
}
return r;
}
#endregion
#region Values
public bool EqualTo(T[] array)
{
ThrowIfNotAllocatedOrInvalid();
return _Span.SequenceEqual<T>(new ReadOnlySpan<T>(array));
}
public void Fill(T value)
{
ThrowIfNotAllocatedOrInvalid();
Span.Fill(value);
}
public void CopyFrom(T[] array)
{
ThrowIfNotAllocatedOrInvalid();
Span<T> s = _Span;
new Span<T>(array).CopyTo(_Span);
}
public T[] CopyToArray()
{
ThrowIfNotAllocatedOrInvalid();
T[] a = new T[this.Length];
_Span.CopyTo(new Span<T>(a));
return a;
}
public unsafe Span<C> GetSpan<C>(int index = 0, int length = 1) where C : struct, IEquatable<C>
{
ThrowIfNotAllocatedOrInvalid();
ThrowIfIndexOutOfRange(index);
ulong s = (ulong) (index * ElementSizeInBytes + length * Unsafe.SizeOf<C>());
if (s > SizeInBytes)
{
SizeIsOutOfRange(s);
}
void* p = BufferHelpers.Add<T>(handle, index).ToPointer();
return new Span<C>(p, length);
}
public unsafe Span<T> Slice(int index) => GetSpan<T>(index, Length - index);
public unsafe Span<T> Slice(int start, int end)
{
if (start >= end)
{
throw new ArgumentOutOfRangeException($"The end {end} of the slice must be greater than the start {start}.");
}
else
{
return GetSpan<T>(start, end - start);
}
}
public unsafe Vector<C> GetVector<C>() where C : struct, IEquatable<C>, IConvertible, IComparable, IFormattable
{
ThrowIfNotAllocatedOrInvalid();
ThrowIfNotNumeric();
if (this.Length != Vector<C>.Count)
{
throw new InvalidOperationException($"The length of the array must be {Vector<C>.Count} elements to create a vector of type {CLRType.Name}.");
}
else
{
return Unsafe.Read<Vector<C>>(voidPtr);
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public unsafe Vector<T> GetSliceAsVector(int index)
{
ThrowIfNotAllocatedOrInvalid();
ThrowIfNotNumeric();
if ((index + VectorLength) > Length)
{
BufferIndexIsOutOfRange(index);
}
return Unsafe.Read<Vector<T>>(BufferHelpers.Add<T>(handle, index).ToPointer());
}
#endregion
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[DebuggerStepThrough]
private void ThrowIfNotAllocatedOrInvalid()
{
if (IsNotAllocated)
{
BufferIsNotAllocated();
}
else if (IsInvalid)
{
HandleIsInvalid();
}
}
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[DebuggerStepThrough]
private void ThrowIfRetained()
{
if (IsRetained)
{
throw new InvalidOperationException($"SafeBuffer<{typeof(T)}[{Length}] has outstanding references.");
}
}
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[DebuggerStepThrough]
private void ThrowIfNotAllocated()
{
if (IsNotAllocated)
{
BufferIsNotAllocated();
}
}
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[DebuggerStepThrough]
private void ThrowIfCannotAcquire()
{
if (!Acquire())
{
throw new InvalidOperationException("Could not acquire handle.");
}
}
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[DebuggerStepThrough]
private void ThrowIfNotVectorisable()
{
if (!IsVectorizable)
{
BufferIsNotVectorisable();
}
}
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[DebuggerStepThrough]
private void ThrowIfNotNumeric()
{
if (!IsNumeric)
{
BufferIsNotNumeric();
}
}
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[DebuggerStepThrough]
private void ThrowIfIndexOutOfRange(int index)
{
if (index < 0 || index >= Length)
{
BufferIndexIsOutOfRange(index);
}
}
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[DebuggerStepThrough]
private void ThrowIfLengthOutOfRange(int length)
{
if (length < 0 || length>= Length)
{
LengthIsOutOfRange(length);
}
}
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[DebuggerStepThrough]
private static void HandleIsInvalid()
{
throw new InvalidOperationException("The handle is invalid.");
}
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[DebuggerStepThrough]
private static void BufferIsNotAllocated()
{
Contract.Assert(false, "Unallocated safe buffer used.");
throw new InvalidOperationException("Unallocated safe buffer used.");
}
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[DebuggerStepThrough]
private static void BufferIsNotVectorisable()
{
Contract.Assert(false, "Buffer is not vectorisable.");
throw new InvalidOperationException("Buffer is not vectorisable.");
}
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[DebuggerStepThrough]
private static void BufferIsNotNumeric()
{
Contract.Assert(false, "Buffer is not numeric.");
throw new InvalidOperationException("Buffer is not numeric.");
}
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[DebuggerStepThrough]
private static void BufferIndexIsOutOfRange(int index)
{
Contract.Assert(false, $"Index {index} into buffer is out of range.");
throw new IndexOutOfRangeException($"Index {index} into buffer is out of range.");
}
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[DebuggerStepThrough]
private static void LengthIsOutOfRange(int length)
{
Contract.Assert(false, $"Length {length} exceeds buffer length.");
throw new Exception($"Length {length} exceeds buffer length.");
}
[ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
[MethodImpl(MethodImplOptions.AggressiveInlining)]
[DebuggerStepThrough]
private static void SizeIsOutOfRange(ulong size)
{
Contract.Assert(false, $"Length {size} exceeds buffer size.");
throw new Exception($"Length {size} exceeds buffer size.");
}
#region Arithmetic
public void VectorFill(T value)
{
Span<Vector<T>> s = GetSpan<Vector<T>>();
Vector<T> fill = new Vector<T>(value);
for (int i = 0; i < s.Length; i++)
{
s[i] = fill;
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void VectorMultiply(T value)
{
ThrowIfNotVectorisable();
Span<Vector<T>> vectorSpan = GetSpan<Vector<T>>();
Vector<T> mulVector = new Vector<T>(value);
for (int i = 0; i < vectorSpan.Length; i++)
{
vectorSpan[i] = Vector.Multiply(vectorSpan[i], mulVector);
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void VectorSqrt()
{
ThrowIfNotVectorisable();
Span<Vector<T>> vector = GetSpan<Vector<T>>();
for (int i = 0; i < vector.Length; i++)
{
vector[i] = Vector.SquareRoot(vector[i]);
}
}
#endregion
#endregion
#region Operators
public ref T this[int index]
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get
{
ThrowIfNotAllocatedOrInvalid();
ThrowIfIndexOutOfRange(index);
return ref this.Read(index);
}
}
#endregion
#region Fields
protected static readonly Type CLRType = typeof(T);
protected static readonly T Element = default;
protected static readonly uint ElementSizeInBytes = (uint) JemUtil.SizeOfStruct<T>();
protected static readonly UInt64 NotAllocated = UInt64.MaxValue;
protected static bool IsNumeric = JemUtil.IsNumericType<T>();
protected static int VectorLength = IsNumeric ? Vector<T>.Count : 0;
protected static bool SIMD = Vector.IsHardwareAccelerated;
protected internal unsafe void* voidPtr;
//Debugger Display = {T[length]}
protected string DebuggerDisplay => string.Format("{{{0}[{1}]}}", typeof(T).Name, Length);
#endregion
}
}
================================================
FILE: jemalloc.Api/SafeBufferEnumerator.cs
================================================
using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using System.Text;
namespace jemalloc
{
/// <summary>Enumerates the elements of a <see cref="SafeBuffer{T}"/>.</summary>
public class SafeBufferEnumerator<T> : IEnumerator, IEnumerator<T> where T : struct, IEquatable<T>
{
/// <summary>The SafeBuffer being enumerated.</summary>
private readonly SafeBuffer<T> _buffer;
/// <summary>The next index to yield.</summary>
private int _index;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal SafeBufferEnumerator(SafeBuffer<T> buffer)
{
_buffer = buffer;
_buffer.Acquire();
_index = -1;
}
/// <summary>Advances the enumerator to the next element of the buffer.</summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public bool MoveNext()
{
int index = _index + 1;
if (index < _buffer.Length)
{
_index = index;
return true;
}
else
{
return false;
}
}
public void Reset()
{
_index = -1;
}
/// <summary>Gets the element at the current position of the enumerator.</summary>
object IEnumerator.Current
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _buffer[_index];
}
public T Current
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => _buffer[_index];
}
void IDisposable.Dispose()
{
_buffer.Release();
}
}
}
================================================
FILE: jemalloc.Api/Utf8Buffer.cs
================================================
//B
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Buffers;
using System.Buffers.Text;
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Text;
using System.Text.Primitives;
using System.Text.Utf8;
namespace jemalloc
{
[DebuggerDisplay("{ToString()} utf8")]
public readonly struct Utf8Buffer : IEquatable<Utf8Buffer>, IRetainable, IDisposable
{
#region Constructors
public Utf8Buffer(ReadOnlySpan<byte> utf8Bytes) => buffer = new FixedBuffer<byte>(utf8Bytes);
public Utf8Buffer(Utf8Span utf8Span) : this(utf8Span.Bytes) { }
public Utf8Buffer(string utf16String)
{
if (utf16String == null)
{
throw new ArgumentNullException(nameof(utf16String));
}
if (utf16String == string.Empty)
{
buffer = new FixedBuffer<byte>();
}
else
{
byte[] b = Encoding.UTF8.GetBytes(utf16String);
buffer = new FixedBuffer<byte>(b);
}
}
private Utf8Buffer(byte[] utf8Bytes) => buffer = new FixedBuffer<byte>(utf8Bytes);
#endregion
#region Implemented members
public void Retain() => buffer.Retain();
public bool Release() => buffer.Release();
#region Disposer
void IDisposable.Dispose()
{
if (IsRetained)
{
throw new InvalidOperationException($"FixedString<[{this.Length}] has outstanding references.");
}
else
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
#endregion
#endregion
#region Overidden members
public override int GetHashCode() => Span.GetHashCode();
public override string ToString() => Span.ToString();
public override bool Equals(object obj)
{
if (obj is Utf8Buffer)
{
return Equals((Utf8Buffer)obj);
}
if (obj is string)
{
return Equals((string)obj);
}
return false;
}
#endregion
#region Properties
public static Utf8Buffer Empty => s_empty;
public bool IsEmpty => Bytes.Length == 0;
public bool IsRetained => buffer.IsRetained;
public int Length => buffer.Length;
public ReadOnlySpan<byte> Bytes => buffer.Span;
internal Utf8Span Span
{
get
{
ThrowIfInvalid();
return new Utf8Span(this);
}
}
#endregion
#region Operators
public ref byte this[int index]
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => ref this.buffer[index];
}
public static bool operator ==(Utf8Buffer left, Utf8Buffer right) => left.Equals(right);
public static bool operator !=(Utf8Buffer left, Utf8Buffer right) => !left.Equals(right);
public static bool operator ==(Utf8Buffer left, Utf8Span right) => left.Equals(right);
public static bool operator !=(Utf8Buffer left, Utf8Span right) => !left.Equals(right);
public static bool operator ==(Utf8Span left, Utf8Buffer right) => right.Equals(left);
public static bool operator !=(Utf8Span left, Utf8Buffer right) => !right.Equals(left);
// TODO: do we like all these O(N) operators?
public static bool operator ==(Utf8Buffer left, string right) => left.Equals(right);
public static bool operator !=(Utf8Buffer left, string right) => !left.Equals(right);
public static bool operator ==(string left, Utf8Buffer right) => right.Equals(left);
public static bool operator !=(string left, Utf8Buffer right) => !right.Equals(left);
public static implicit operator ReadOnlySpan<byte>(Utf8Buffer utf8String) => utf8String.Bytes;
public static implicit operator Utf8Span(Utf8Buffer utf8String) => utf8String.Span;
public static explicit operator Utf8Buffer(string utf16String) => new Utf8Buffer(utf16String);
public static explicit operator string(Utf8Buffer utf8String) => utf8String.ToString();
#endregion
#region Methods
public void ThrowIfInvalid() => buffer.ThrowIfInvalid();
public bool Free() => buffer.Free();
public bool Equals(Utf8Buffer other) => Bytes.SequenceEqual(other.Bytes);
public bool Equals(Utf8Span other) => Bytes.SequenceEqual(other.Bytes);
public bool Equals(string other) => Span.Equals(other);
public Utf8CodePointEnumerator GetEnumerator() => new Utf8CodePointEnumerator(buffer.Span);
public int CompareTo(Utf8Buffer other) => Span.CompareTo(other);
public int CompareTo(string other) => Span.CompareTo(other);
public int CompareTo(Utf8Span other) => Span.CompareTo(other);
public bool StartsWith(uint codePoint) => Span.StartsWith(codePoint);
public bool StartsWith(Utf8Buffer value) => Span.StartsWith(value.Span);
public bool StartsWith(Utf8Span value) => Span.StartsWith(value);
public bool EndsWith(Utf8Buffer value) => Span.EndsWith(value.Span);
public bool EndsWith(Utf8Span value) => Span.EndsWith(value);
public bool EndsWith(uint codePoint) => Span.EndsWith(codePoint);
#region Slicing
// TODO: should Utf8String slicing operations return Utf8Span?
// TODO: should we add slicing overloads that take char delimiters?
// TODO: why do we even have Try versions? If the delimiter is not found, the result should be the original.
public bool TrySubstringFrom(Utf8Buffer value, out Utf8Buffer result)
{
int idx = IndexOf(value);
if (idx == StringNotFound)
{
result = default;
return false;
}
result = Substring(idx);
return true;
}
public bool TrySubstringFrom(uint codePoint, out Utf8Buffer result)
{
int idx = IndexOf(codePoint);
if (idx == StringNotFound)
{
result = default;
return false;
}
result = Substring(idx);
return true;
}
public bool TrySubstringTo(Utf8Buffer value, out Utf8Buffer result)
{
int idx = IndexOf(value);
if (idx == StringNotFound)
{
result = default;
return false;
}
result = Substring(0, idx);
return true;
}
public bool TrySubstringTo(uint codePoint, out Utf8Buffer result)
{
int idx = IndexOf(codePoint);
if (idx == StringNotFound)
{
result = default;
return false;
}
result = Substring(0, idx);
return true;
}
#endregion
#region Index-based operations
// TODO: should we even have index based operations?
// TODO: should we have search (e.g. IndexOf) overlaods that take char?
public Utf8Buffer Substring(int index) => index == 0 ? this : Substring(index, Bytes.Length - index);
public Utf8Buffer Substring(int index, int length)
{
if (length == 0)
{
return Empty;
}
if (index == 0 && length == Bytes.Length) return this;
return new Utf8Buffer(buffer.Span.Slice(index, length));
}
public int IndexOf(Utf8Buffer value) => Bytes.IndexOf(value.Bytes);
public int IndexOf(uint codePoint) => Span.IndexOf(codePoint);
public int IndexOf(string s) => Span.IndexOf(new Utf8Span(Encoding.UTF8.GetBytes(s)));
public int LastIndexOf(Utf8Buffer value) => Span.LastIndexOf(value.Span);
public int LastIndexOf(uint codePoint) => Span.LastIndexOf(codePoint);
public bool TryFormat(Span<byte> buffer, out int written, StandardFormat format = default, SymbolTable symbolTable = null)
{
if (!format.IsDefault) throw new ArgumentOutOfRangeException(nameof(format));
if (symbolTable == SymbolTable.InvariantUtf8)
{
written = Bytes.Length;
return Bytes.TryCopyTo(buffer);
}
return symbolTable.TryEncode(Bytes, buffer, out var consumed, out written);
}
#endregion
/*
// TODO: unless we change the type of Trim to Utf8Span, this double allocates.
public FixedUtf8String Trim() => TrimStart().TrimEnd();
// TODO: implement Utf8String.Trim(uint[])
public FixedString Trim(uint[] codePoints) => throw new NotImplementedException();
public FixedString TrimStart()
{
Utf8CodePointEnumerator it = GetEnumerator();
while (it.MoveNext() &&Char.IsWhiteSpace(it.Current)) { }
return Substring(it.PositionInCodeUnits);
}
public FixedUtf8String TrimStart(uint[] codePoints) {
if (codePoints == null || codePoints.Length == 0) return TrimStart(); // Trim Whitespace
Utf8CodePointEnumerator it = GetEnumerator();
while (it.MoveNext()) {
if(Array.IndexOf(codePoints, it.Current) == -1){
break;
}
}
return Substring(it.PositionInCodeUnits);
}
// TODO: do we even want this overload? System.String does not have an overload that takes string
public FixedString TrimStart(FixedString characters)
{
if (characters == Empty)
{
// Trim Whitespace
return TrimStart();
}
Utf8CodePointEnumerator it = GetEnumerator();
Utf8CodePointEnumerator itPrefix = characters.GetEnumerator();
while (it.MoveNext())
{
bool found = false;
// Iterate over prefix set
while (itPrefix.MoveNext())
{
if (it.Current == itPrefix.Current)
{
// Character found, don't check further
found = true;
break;
}
}
if (!found)
{
// Reached the end, char was not found
break;
}
itPrefix.Reset();
}
return Substring(it.PositionInCodeUnits);
}
public FixedString TrimEnd()
{
var it = new Utf8CodePointReverseEnumerator(Bytes);
while (it.MoveNext() && Unicode.IsWhitespace(it.Current))
{
}
return Substring(0, it.PositionInCodeUnits);
}
// TODO: implement Utf8String.TrimEnd(uint[])
public FixedString TrimEnd(uint[] codePoints) => throw new NotImplementedException();
// TODO: do we even want this overload? System.String does not have an overload that takes string
public FixedString TrimEnd(FixedString characters)
{
if (characters == Empty)
{
// Trim Whitespace
return TrimEnd();
}
var it = new Utf8CodePointReverseEnumerator(Bytes);
Utf8CodePointEnumerator itPrefix = characters.GetEnumerator();
while (it.MoveNext())
{
bool found = false;
// Iterate over prefix set
while (itPrefix.MoveNext())
{
if (it.Current == itPrefix.Current)
{
// Character found, don't check further
found = true;
break;
}
}
if (!found)
{
// Reached the end, char was not found
break;
}
itPrefix.Reset();
}
return Substring(0, it.PositionInCodeUnits);
}
*/
#region Disposer
private void Dispose(bool disposing)
{
buffer.Free();
}
#endregion
#endregion
#region Fields
//private readonly byte[] _buffer;
private readonly FixedBuffer<byte> buffer;
private const int StringNotFound = -1;
static Utf8Buffer s_empty = new Utf8Buffer(string.Empty);
#endregion
}
}
================================================
FILE: jemalloc.Api/jemalloc.Api.csproj
================================================
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<Platforms>AnyCPU;x64</Platforms>
<RootNamespace>jemalloc</RootNamespace>
<LangVersion>latest</LangVersion>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<PackageId>jemalloc.NET</PackageId>
<Version>0.2.4-alpha</Version>
<Authors>Allister Beharry</Authors>
<Company />
<Product>jemalloc.NET</Product>
<AssemblyVersion>0.2.4.0</AssemblyVersion>
<FileVersion>0.2.4.0</FileVersion>
<PackageProjectUrl>https://github.com/allisterb/jemalloc.NET</PackageProjectUrl>
<PackageLicenseUrl>https://github.com/allisterb/jemalloc.NET/LICENSE</PackageLicenseUrl>
<RepositoryUrl>https://github.com/allisterb/jemalloc.NET</RepositoryUrl>
<Description>Native memory manager for .NET</Description>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<LangVersion>latest</LangVersion>
<PlatformTarget>x64</PlatformTarget>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<OutputPath>..\x64\Debug\</OutputPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<PlatformTarget>x64</PlatformTarget>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<OutputPath>..\x64\Debug\</OutputPath>
<LangVersion>latest</LangVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<PlatformTarget>x64</PlatformTarget>
<LangVersion>latest</LangVersion>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<OutputPath>..\x64\Release\</OutputPath>
<DebugType>portable</DebugType>
<DebugSymbols>true</DebugSymbols>
</PropertyGroup>
<ItemGroup>
<Compile Remove="Utf16LittleEndianCodePointEnumerator.cs" />
<Compile Remove="Utf8CodePointReverseEnumerator.cs" />
<Compile Remove="Utf8Helper.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="System.Collections.Immutable" Version="1.4.0" />
<PackageReference Include="System.Memory" Version="4.5.0-preview1-26021-02" />
<PackageReference Include="System.Numerics.Vectors" Version="4.5.0-preview2-25707-02" />
<PackageReference Include="System.Reflection.Emit" Version="4.3.0" />
<PackageReference Include="System.Reflection.Emit.ILGeneration" Version="4.3.0" />
<PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="4.5.0-preview2-25707-02" />
<PackageReference Include="System.Text.Utf8String" Version="0.1.0-e171221-2" />
</ItemGroup>
<Target Name="PostBuild" AfterTargets="PostBuildEvent">
<Exec Command="copy $(ProjectDir)..\x64\Debug\jemallocd.dll $(TargetDir)" />
</Target>
</Project>
================================================
FILE: jemalloc.Api/jemalloc.cs
================================================
using System;
using System.Runtime.ConstrainedExecution;
using System.Runtime.InteropServices;
using System.Security;
namespace jemalloc
{
#region Delegates
[SuppressUnmanagedCodeSecurity, UnmanagedFunctionPointer(global::System.Runtime.InteropServices.CallingConvention.Cdecl)]
public unsafe delegate global::System.IntPtr ExtentAllocT(global::System.IntPtr _0, global::System.IntPtr _1, ulong _2, ulong _3, bool* _4, bool* _5, uint
gitextract_gm5xlq0e/ ├── .gitattributes ├── .gitignore ├── .gitmodules ├── LICENSE ├── README.md ├── build.cmd ├── jemalloc.Api/ │ ├── Buffer.cs │ ├── BufferHelpers.cs │ ├── Extensions/ │ │ └── TypeExtensions.cs │ ├── ExtentHooks.cs │ ├── FixedBuffer.cs │ ├── FixedBufferAllocation.cs │ ├── FixedBufferEnumerator.cs │ ├── GDI.cs │ ├── GenericMath.cs │ ├── HugeArray.cs │ ├── HugeBuffer.cs │ ├── HugeBufferEnumerator.cs │ ├── IBufferAllocation.cs │ ├── JemApi.cs │ ├── JemPinnable.cs │ ├── JemUtil.cs │ ├── MemoryRef.cs │ ├── NDArray.cs │ ├── SafeArray.cs │ ├── SafeBuffer.cs │ ├── SafeBufferEnumerator.cs │ ├── Utf8Buffer.cs │ ├── jemalloc.Api.csproj │ └── jemalloc.cs ├── jemalloc.Benchmarks/ │ ├── BenchmarkStatisticColumn.cs │ ├── Benchmarks/ │ │ ├── FixedBufferVsManagedArray.cs │ │ ├── HugeNativeVsManagedArray.cs │ │ ├── MallocVsArray.cs │ │ ├── SafeVsManagedArray.cs │ │ └── Vector.cs │ ├── Design.md │ ├── JemBenchmark.cs │ ├── JemBenchmarkAttribute.cs │ ├── JemBenchmarkJobAttribute.cs │ ├── JemBenchmarkParam.cs │ ├── JemStatisticColumn.cs │ ├── ProcessStatisticColumn.cs │ ├── TestUDT.cs │ └── jemalloc.Benchmarks.csproj ├── jemalloc.Bindings/ │ ├── App.config │ ├── JemallocLibrary.cs │ ├── Program.cs │ ├── Properties/ │ │ └── AssemblyInfo.cs │ ├── jemalloc-win-msvc.h │ ├── jemalloc.Bindings.csproj │ └── packages.config ├── jemalloc.Buffers/ │ ├── JemPinnable.cs │ ├── NativeHelpers.cs │ ├── NativeMemory.cs │ └── jemalloc.Buffers.csproj ├── jemalloc.Cli/ │ ├── Options.cs │ ├── Program.cs │ ├── Properties/ │ │ └── PublishProfiles/ │ │ └── ReleaseProfile.pubxml │ └── jemalloc.Cli.csproj ├── jemalloc.Examples/ │ ├── TestUDT.cs │ └── jemalloc.Examples.csproj ├── jemalloc.NET.sln ├── jemalloc.StressTests/ │ ├── FixedBufferStressTests.cs │ └── jemalloc.StressTests.csproj ├── jemalloc.Tests/ │ ├── BufferTests.cs │ ├── FixedBufferTests.cs │ ├── HugeArrayTests.cs │ ├── MallCtlTests.cs │ ├── MallocConfTests.cs │ ├── MallocMessageTests.cs │ ├── MallocTests.cs │ ├── SafeArrayTests.cs │ ├── UDTTests.cs │ ├── Utf8BufferTests.cs │ ├── VectorTests.cs │ ├── jemalloc.Tests.csproj │ └── jemallocTest.cs └── jembench.cmd
SYMBOL INDEX (645 symbols across 58 files)
FILE: jemalloc.Api/Buffer.cs
type Buffer (line 8) | public ref struct Buffer<T> where T : struct
method Buffer (line 10) | public Buffer(int length)
method Allocate (line 93) | private unsafe bool Allocate(int length)
method Release (line 108) | public void Release()
method Fill (line 121) | public void Fill(T value)
FILE: jemalloc.Api/BufferHelpers.cs
class BufferHelpers (line 14) | internal static partial class BufferHelpers
method IndexOf (line 16) | public static int IndexOf(ref byte searchSpace, int searchSpaceLength,...
method IndexOfAny (line 51) | public static int IndexOfAny(ref byte searchSpace, int searchSpaceLeng...
method IndexOf (line 81) | public static int IndexOf<T>(ref T searchSpace, int searchSpaceLength,...
method IndexOf (line 117) | public static unsafe int IndexOf<T>(ref T searchSpace, T value, int le...
method SequenceEqual (line 191) | public static bool SequenceEqual<T>(ref T first, ref T second, int len...
method CopyTo (line 264) | public static unsafe void CopyTo<T>(ref T dst, int dstLength, ref T sr...
method Add (line 343) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method IsReferenceOrContainsReferences (line 370) | public static bool IsReferenceOrContainsReferences<T>() => PerTypeValues...
method IsReferenceOrContainsReferencesCore (line 372) | private static bool IsReferenceOrContainsReferencesCore(Type type)
method IsReferenceOrContainsReferences (line 398) | public static bool IsReferenceOrContainsReferences(Type type, out FieldI...
class PerTypeValues (line 430) | public static class PerTypeValues<T>
method MeasureArrayAdjustment (line 443) | private static IntPtr MeasureArrayAdjustment()
method ClearLessThanPointerSized (line 450) | public unsafe static void ClearLessThanPointerSized(byte* ptr, UIntPtr b...
method ClearLessThanPointerSized (line 475) | public static unsafe void ClearLessThanPointerSized(ref byte b, UIntPtr ...
method ClearPointerSizedWithoutReferences (line 501) | public unsafe static void ClearPointerSizedWithoutReferences(ref byte b,...
method ClearPointerSizedWithReferences (line 537) | public unsafe static void ClearPointerSizedWithReferences(ref IntPtr ip,...
method LessThanEqual (line 575) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
type Reg64 (line 583) | [StructLayout(LayoutKind.Sequential, Size = 64)]
type Reg32 (line 585) | [StructLayout(LayoutKind.Sequential, Size = 32)]
type Reg16 (line 587) | [StructLayout(LayoutKind.Sequential, Size = 16)]
FILE: jemalloc.Api/Extensions/TypeExtensions.cs
class TypeExtensions (line 11) | public static class TypeExtensions
method IsNullable (line 20) | public static bool IsNullable(this Type type)
method GetUnderlyingType (line 39) | public static Type GetUnderlyingType(this Type type)
method IsSameOrParent (line 62) | public static bool IsSameOrParent(Type parent, Type child)
method ThrowIfNotUnmanagedType (line 101) | public static void ThrowIfNotUnmanagedType(this Type type)
method ThrowIfNotUnmanagedType (line 106) | private static void ThrowIfNotUnmanagedType(Type type, Stack<Type> typ...
method TranslateGenericParameters (line 151) | public static Type TranslateGenericParameters(this Type type, Type[] t...
FILE: jemalloc.Api/ExtentHooks.cs
class ExtentHooks (line 7) | public unsafe partial class ExtentHooks : IDisposable
type __Internal (line 9) | [StructLayout(LayoutKind.Explicit, Size = 72)]
method cctor (line 39) | [SuppressUnmanagedCodeSecurity]
method __CreateInstance (line 53) | internal static global::jemalloc.ExtentHooks __CreateInstance(global::...
method __CreateInstance (line 58) | internal static global::jemalloc.ExtentHooks __CreateInstance(global::...
method __CopyValue (line 63) | private static void* __CopyValue(global::jemalloc.ExtentHooks.__Intern...
method ExtentHooks (line 70) | private ExtentHooks(global::jemalloc.ExtentHooks.__Internal native, bo...
method ExtentHooks (line 77) | protected ExtentHooks(void* native, bool skipVTables = false)
method ExtentHooks (line 84) | public ExtentHooks()
method ExtentHooks (line 91) | public ExtentHooks(global::jemalloc.ExtentHooks _0)
method Dispose (line 99) | public void Dispose()
method Dispose (line 104) | public virtual void Dispose(bool disposing)
FILE: jemalloc.Api/FixedBuffer.cs
type FixedBuffer (line 13) | [StructLayout(LayoutKind.Sequential)]
method FixedBuffer (line 18) | public FixedBuffer(int length)
method FixedBuffer (line 46) | public FixedBuffer(int length, bool isReadOnly) : this(length)
method FixedBuffer (line 51) | public FixedBuffer(T[] array) : this(array.Length)
method FixedBuffer (line 57) | public FixedBuffer(Span<T> span) : this(span.Length)
method FixedBuffer (line 61) | public FixedBuffer(ReadOnlySpan<T> span) : this(span.Length)
method Retain (line 69) | public void Retain()
method Release (line 74) | public bool Release()
method Equals (line 88) | bool IEquatable<FixedBuffer<T>>.Equals(FixedBuffer<T> buffer)
method GetEnumerator (line 95) | public IEnumerator<T> GetEnumerator() => new FixedBufferEnumerator<T>(...
method GetEnumerator (line 97) | IEnumerator IEnumerable.GetEnumerator() => new FixedBufferEnumerator<T...
method Dispose (line 100) | void IDisposable.Dispose()
method Dispose (line 110) | private void Dispose(bool disposing)
method Acquire (line 199) | public void Acquire() => Retain();
method Free (line 201) | public bool Free()
method Fill (line 214) | public void Fill(T value)
method CopyTo (line 219) | public void CopyTo(T[] array)
method CopyToArray (line 224) | public T[] CopyToArray()
method CopyToArray (line 231) | public T[] CopyToArray(T[] array)
method CopyToArrayAndFree (line 244) | public T[] CopyToArrayAndFree()
method EqualTo (line 251) | public bool EqualTo(T[] array)
method AcquireSpan (line 266) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method AcquireSpan (line 273) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method Slice (line 289) | public ReadOnlySpan<T> Slice(int start, int length)
method PtrTo (line 294) | public unsafe void * PtrTo(int index)
method AcquireAsSingleVector (line 299) | public Vector<T> AcquireAsSingleVector()
method AcquireVectorSpan (line 310) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method AcquireWriteSpan (line 318) | public unsafe Span<T> AcquireWriteSpan()
method AcquireVectorWriteSpan (line 324) | public unsafe Span<Vector<T>> AcquireVectorWriteSpan()
method Read (line 331) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method Read (line 338) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method Write (line 346) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method ThrowIfInvalid (line 361) | internal void ThrowIfInvalid()
method ThrowIfIndexOutOfRange (line 369) | internal void ThrowIfIndexOutOfRange(int index)
method ThrowIfRefCountNonZero (line 381) | internal void ThrowIfRefCountNonZero()
method ThrowIfReadOnly (line 389) | internal void ThrowIfReadOnly()
method ThrowIfTypeNotPrimitive (line 397) | internal void ThrowIfTypeNotPrimitive()
method ThrowIfNotVectorizable (line 405) | internal void ThrowIfNotVectorizable()
method DebuggerDisplay (line 417) | private string DebuggerDisplay() => string.Format("{{{0}[{1}]}}", type...
method VectorFill (line 420) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method VectorMultiply (line 434) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method VectorSqrt (line 456) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method VectorLessThanAll (line 477) | public unsafe bool VectorLessThanAll(T value, out int index)
FILE: jemalloc.Api/FixedBufferAllocation.cs
type FixedBufferAllocation (line 7) | public readonly struct FixedBufferAllocation : IEquatable<FixedBufferAll...
method FixedBufferAllocation (line 10) | public FixedBufferAllocation(IntPtr ptr, ulong size, long timestamp, i...
method GetHashCode (line 21) | public override int GetHashCode()
method Equals (line 26) | public override bool Equals(object obj)
method Equals (line 39) | bool IEquatable<FixedBufferAllocation>.Equals(FixedBufferAllocation ot...
class FixedBufferComparator (line 52) | public class FixedBufferComparator : IEqualityComparer<FixedBufferAlloca...
method Equals (line 54) | public bool Equals(FixedBufferAllocation l, FixedBufferAllocation r)
method GetHashCode (line 59) | public int GetHashCode(FixedBufferAllocation a)
FILE: jemalloc.Api/FixedBufferEnumerator.cs
class FixedBufferEnumerator (line 9) | public class FixedBufferEnumerator<T> : IEnumerator, IEnumerator<T> wher...
method FixedBufferEnumerator (line 16) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method MoveNext (line 25) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method Reset (line 41) | public void Reset()
method Dispose (line 59) | void IDisposable.Dispose()
FILE: jemalloc.Api/GDI.cs
class Win32 (line 8) | public unsafe static partial class Win32
type BitmapCompressionMode (line 10) | public enum BitmapCompressionMode
type BITMAPINFOHEADER (line 23) | [StructLayout(LayoutKind.Sequential)]
method Init (line 38) | public void Init()
type RGBQUAD (line 44) | [StructLayout(LayoutKind.Sequential)]
type BITMAPINFO (line 53) | public struct BITMAPINFO
method CreateDIBitmap (line 63) | [DllImport("gdi32.dll")]
FILE: jemalloc.Api/GenericMath.cs
class GM (line 7) | public static class GM<TData> where TData : struct, IEquatable<TData>, I...
method GM (line 10) | static GM()
method Const (line 25) | public static TData Const<TValue>(TValue v) where TValue : struct, IEq...
method Multiply (line 30) | public static TData Multiply(TData l, TData r)
method Sqrt (line 73) | public static double Sqrt(TData n)
method F (line 105) | public static double F(Func<double, double> f, TData n)
method Random (line 136) | public static TData Random()
method Random (line 169) | public static TData Random(double max)
method RandomMultiplyFactorAndValue (line 174) | public static (TData, TData) RandomMultiplyFactorAndValue()
FILE: jemalloc.Api/HugeArray.cs
class HugeArray (line 7) | public class HugeArray<T> : HugeBuffer<T> where T : struct, IEquatable<T>
method HugeArray (line 9) | public HugeArray(ulong length, params T[] values) : base(length, value...
FILE: jemalloc.Api/HugeBuffer.cs
class HugeBuffer (line 16) | public abstract class HugeBuffer<T> : SafeHandle, IRetainable, IDisposab...
method HugeBuffer (line 19) | protected HugeBuffer(ulong length, params T[] values) : base(IntPtr.Ze...
method ReleaseHandle (line 40) | [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
method Dispose (line 64) | [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
method Retain (line 82) | public void Retain() => Acquire();
method Release (line 84) | [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
method Equals (line 100) | public bool Equals(HugeBuffer<T> other)
method GetEnumerator (line 106) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method GetEnumerator (line 109) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method Allocate (line 135) | protected unsafe virtual IntPtr Allocate(ulong length)
method InitSegments (line 153) | protected unsafe void InitSegments()
method InitVectors (line 171) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method _GetSegmentIndex (line 186) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method _GetSegment (line 192) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method _GetSegmentSpan (line 201) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method _GetSegmentVectorSpan (line 208) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method _Read (line 215) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method _Write (line 227) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method Acquire (line 239) | [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
method Release (line 253) | public bool Release(int n)
method EqualTo (line 274) | public bool EqualTo(T[] array)
method Fill (line 284) | public unsafe void Fill(T value)
method CopyFrom (line 294) | public void CopyFrom(T[] array)
method CopyToArray (line 300) | public T[] CopyToArray()
method GetSpan (line 312) | public unsafe Span<C> GetSpan<C>(ulong index = 0, int length = 1) wher...
method Slice (line 326) | public unsafe Span<T> Slice(ulong start, ulong end)
method GetAsSingleVector (line 345) | public unsafe Vector<T> GetAsSingleVector()
method GetSliceSegmentAsVectorSpan (line 355) | public unsafe Span<Vector<T>> GetSliceSegmentAsVectorSpan(ulong index)
method GetSliceAsSingleVector (line 371) | public unsafe Vector<T> GetSliceAsSingleVector(ulong index)
method ThrowIfCannotAcquire (line 407) | [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
method ThrowIfIndexOutOfRange (line 418) | [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
method ThrowIfNotAllocatedOrInvalid (line 429) | [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
method ThrowIfRetained (line 444) | [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
method ThrowIfNotAllocated (line 455) | [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
method ThrowIfNotVectorisable (line 466) | [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
method ThrowIfNotNumeric (line 477) | [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
method HandleIsInvalid (line 488) | [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
method BufferIsNotAllocated (line 497) | [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
method BufferIsNotVectorisable (line 506) | [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
method BufferIsNotNumeric (line 515) | [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
method BufferIndexIsOutOfRange (line 524) | [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
method BufferSizeIsOutOfRange (line 533) | [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
FILE: jemalloc.Api/HugeBufferEnumerator.cs
class HugeBufferEnumerator (line 10) | public class HugeBufferEnumerator<T> : IEnumerator, IEnumerator<T> where...
method HugeBufferEnumerator (line 17) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method MoveNext (line 26) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method Reset (line 49) | public void Reset()
method Dispose (line 67) | void IDisposable.Dispose()
FILE: jemalloc.Api/IBufferAllocation.cs
type IBufferAllocation (line 7) | public interface IBufferAllocation
FILE: jemalloc.Api/JemApi.cs
class CallerInformation (line 17) | public class CallerInformation
method CallerInformation (line 23) | public CallerInformation(string name, string file, int line_number)
method ToString (line 30) | public override string ToString() => Jem.GetCallerDetails(this);
type ERRNO (line 34) | internal enum ERRNO
type ALLOC_FLAGS (line 74) | [Flags]
method Jem (line 85) | static Jem()
method Malloc (line 94) | public static global::System.IntPtr Malloc(ulong size, [CallerMemberName...
method Calloc (line 112) | public static global::System.IntPtr Calloc(ulong num, ulong size, [Calle...
method PosixMemalign (line 130) | public static int PosixMemalign(void** memptr, ulong alignment, ulong size)
method AlignedAlloc (line 137) | public static global::System.IntPtr AlignedAlloc(ulong alignment, ulong ...
method Realloc (line 144) | public static global::System.IntPtr Realloc(global::System.IntPtr ptr, u...
method Free (line 151) | [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
method Mallocx (line 177) | public static global::System.IntPtr Mallocx(ulong size, int flags)
method Rallocx (line 184) | public static global::System.IntPtr Rallocx(global::System.IntPtr ptr, u...
method Xallocx (line 191) | public static ulong Xallocx(global::System.IntPtr ptr, ulong size, ulong...
method Sallocx (line 198) | public static ulong Sallocx(global::System.IntPtr ptr, int flags)
method Dallocx (line 205) | public static void Dallocx(global::System.IntPtr ptr, int flags)
method Sdallocx (line 211) | public static void Sdallocx(global::System.IntPtr ptr, ulong size, int f...
method Nallocx (line 217) | public static ulong Nallocx(ulong size, int flags)
method Mallctl (line 224) | public static int Mallctl(string name, global::System.IntPtr oldp, ref u...
method Mallctlnametomib (line 234) | public static int Mallctlnametomib(string name, ref ulong mibp, ref ulon...
method Mallctlbymib (line 248) | public static int Mallctlbymib(ref ulong mib, ulong miblen, global::Syst...
method Init (line 264) | public static bool Init(string conf)
method GetRefCount (line 287) | public static int GetRefCount(IntPtr ptr)
method IncrementRefCount (line 295) | public static void IncrementRefCount(IntPtr ptr)
method DecrementRefCount (line 302) | public static void DecrementRefCount(IntPtr ptr)
method PtrIsAllocated (line 309) | public static bool PtrIsAllocated(IntPtr ptr)
method GetMallocStats (line 320) | public static string GetMallocStats(string opt)
method MallocUsableSize (line 332) | public static ulong MallocUsableSize(global::System.IntPtr ptr)
FILE: jemalloc.Api/JemPinnable.cs
class JemPinnable (line 9) | [StructLayout(LayoutKind.Sequential)]
FILE: jemalloc.Api/JemUtil.cs
class JemUtil (line 15) | public static class JemUtil
method JemUtil (line 18) | static JemUtil()
method CLRType (line 95) | public static Type CLRType<T>() => typeof(T);
method ElementSizeInBytes (line 97) | public static uint ElementSizeInBytes<T>() where T: struct => (uint)Je...
method VectorLength (line 99) | public static int VectorLength<T> () where T : struct => Vector<T>.Count;
method IsNumericType (line 105) | public static bool IsNumericType<T>()
method PtrToSpan (line 110) | public unsafe static Span<T> PtrToSpan<T>(IntPtr ptr, int length)
method PtrToStruct (line 116) | public unsafe static ref readonly T PtrToStruct<T>(void* ptr) where T ...
method ValToGenericStruct (line 121) | public unsafe static TReturn ValToGenericStruct<TValue, TReturn>(TValu...
method SizeOfStruct (line 127) | public static int SizeOfStruct<T>() where T : struct
method CombineHashCodes (line 134) | public static int CombineHashCodes(params int[] hashCodes)
method PrintSize (line 153) | public static string PrintSize(double bytes, string suffix = "")
method PrintBytes (line 179) | public static string PrintBytes(double bytes, string suffix = "")
method PrintBytesToTuple (line 205) | public static Tuple<double, string> PrintBytesToTuple(double bytes, st...
method GetCurrentThreadCycles (line 211) | public unsafe static ulong GetCurrentThreadCycles()
type __Internal (line 238) | public partial struct __Internal
type DuplicateOptions (line 240) | [Flags]
method QueryThreadCycleTime (line 247) | [DllImport("kernel32.dll", SetLastError = true)]
method GetCurrentThread (line 251) | [DllImport("kernel32.dll", SetLastError = true)]
method GetCurrentProcess (line 255) | [DllImport("kernel32.dll", SetLastError = true)]
method DuplicateHandle (line 259) | [DllImport("kernel32.dll", SetLastError = true)]
method CloseHandle (line 264) | [DllImport("kernel32.dll", SetLastError = true)]
method QueryPerformanceCounter (line 270) | [DllImport("kernel32.dll", SetLastError = true)]
FILE: jemalloc.Api/MemoryRef.cs
type MemoryRef (line 8) | public readonly ref struct MemoryRef<T> where T : struct
method MemoryRef (line 10) | internal MemoryRef(Guid guid, MemoryHandle h)
method Release (line 17) | public bool Release()
FILE: jemalloc.Api/NDArray.cs
class NDArray (line 8) | public class NDArray<T> where T : struct
method NDArray (line 10) | public NDArray(ulong points, int rank)
FILE: jemalloc.Api/SafeArray.cs
class SafeArray (line 10) | public class SafeArray<T> : SafeBuffer<T> where T : struct, IEquatable<T>
method SafeArray (line 12) | public SafeArray(int length, params T[] values) : base(length, values) {}
FILE: jemalloc.Api/SafeBuffer.cs
class SafeBuffer (line 16) | public abstract class SafeBuffer<T> : SafeHandle, IRetainable, IDisposab...
method SafeBuffer (line 19) | protected SafeBuffer(int length, params T[] values) : base(IntPtr.Zero...
method ReleaseHandle (line 40) | [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
method Dispose (line 64) | [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
method Retain (line 81) | public void Retain() => Acquire();
method Release (line 83) | [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
method Equals (line 99) | public bool Equals(SafeBuffer<T> other)
method GetEnumerator (line 105) | public IEnumerator<T> GetEnumerator() => new SafeBufferEnumerator<T>(t...
method GetEnumerator (line 107) | IEnumerator IEnumerable.GetEnumerator() => new SafeBufferEnumerator<T>...
method Allocate (line 143) | protected unsafe virtual IntPtr Allocate(int length)
method InitVector (line 160) | protected void InitVector()
method Read (line 173) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method Write (line 181) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method Acquire (line 190) | [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
method Release (line 204) | public bool Release(int n)
method EqualTo (line 225) | public bool EqualTo(T[] array)
method Fill (line 232) | public void Fill(T value)
method CopyFrom (line 239) | public void CopyFrom(T[] array)
method CopyToArray (line 246) | public T[] CopyToArray()
method GetSpan (line 254) | public unsafe Span<C> GetSpan<C>(int index = 0, int length = 1) where ...
method Slice (line 267) | public unsafe Span<T> Slice(int index) => GetSpan<T>(index, Length - i...
method Slice (line 269) | public unsafe Span<T> Slice(int start, int end)
method GetVector (line 281) | public unsafe Vector<C> GetVector<C>() where C : struct, IEquatable<C>...
method GetSliceAsVector (line 295) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method ThrowIfNotAllocatedOrInvalid (line 309) | [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
method ThrowIfRetained (line 324) | [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
method ThrowIfNotAllocated (line 335) | [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
method ThrowIfCannotAcquire (line 346) | [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
method ThrowIfNotVectorisable (line 357) | [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
method ThrowIfNotNumeric (line 368) | [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
method ThrowIfIndexOutOfRange (line 380) | [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
method ThrowIfLengthOutOfRange (line 391) | [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
method HandleIsInvalid (line 403) | [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
method BufferIsNotAllocated (line 411) | [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
method BufferIsNotVectorisable (line 420) | [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
method BufferIsNotNumeric (line 429) | [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
method BufferIndexIsOutOfRange (line 438) | [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
method LengthIsOutOfRange (line 447) | [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
method SizeIsOutOfRange (line 456) | [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
method VectorFill (line 466) | public void VectorFill(T value)
method VectorMultiply (line 476) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method VectorSqrt (line 488) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
FILE: jemalloc.Api/SafeBufferEnumerator.cs
class SafeBufferEnumerator (line 10) | public class SafeBufferEnumerator<T> : IEnumerator, IEnumerator<T> where...
method SafeBufferEnumerator (line 17) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method MoveNext (line 26) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method Reset (line 42) | public void Reset()
method Dispose (line 60) | void IDisposable.Dispose()
FILE: jemalloc.Api/Utf8Buffer.cs
type Utf8Buffer (line 17) | [DebuggerDisplay("{ToString()} utf8")]
method Utf8Buffer (line 21) | public Utf8Buffer(ReadOnlySpan<byte> utf8Bytes) => buffer = new FixedB...
method Utf8Buffer (line 23) | public Utf8Buffer(Utf8Span utf8Span) : this(utf8Span.Bytes) { }
method Utf8Buffer (line 25) | public Utf8Buffer(string utf16String)
method Utf8Buffer (line 43) | private Utf8Buffer(byte[] utf8Bytes) => buffer = new FixedBuffer<byte>...
method Retain (line 48) | public void Retain() => buffer.Retain();
method Release (line 49) | public bool Release() => buffer.Release();
method Dispose (line 51) | void IDisposable.Dispose()
method GetHashCode (line 67) | public override int GetHashCode() => Span.GetHashCode();
method ToString (line 69) | public override string ToString() => Span.ToString();
method Equals (line 71) | public override bool Equals(object obj)
method ThrowIfInvalid (line 138) | public void ThrowIfInvalid() => buffer.ThrowIfInvalid();
method Free (line 140) | public bool Free() => buffer.Free();
method Equals (line 142) | public bool Equals(Utf8Buffer other) => Bytes.SequenceEqual(other.Bytes);
method Equals (line 144) | public bool Equals(Utf8Span other) => Bytes.SequenceEqual(other.Bytes);
method Equals (line 146) | public bool Equals(string other) => Span.Equals(other);
method GetEnumerator (line 148) | public Utf8CodePointEnumerator GetEnumerator() => new Utf8CodePointEnu...
method CompareTo (line 150) | public int CompareTo(Utf8Buffer other) => Span.CompareTo(other);
method CompareTo (line 152) | public int CompareTo(string other) => Span.CompareTo(other);
method CompareTo (line 154) | public int CompareTo(Utf8Span other) => Span.CompareTo(other);
method StartsWith (line 156) | public bool StartsWith(uint codePoint) => Span.StartsWith(codePoint);
method StartsWith (line 158) | public bool StartsWith(Utf8Buffer value) => Span.StartsWith(value.Span);
method StartsWith (line 160) | public bool StartsWith(Utf8Span value) => Span.StartsWith(value);
method EndsWith (line 162) | public bool EndsWith(Utf8Buffer value) => Span.EndsWith(value.Span);
method EndsWith (line 164) | public bool EndsWith(Utf8Span value) => Span.EndsWith(value);
method EndsWith (line 166) | public bool EndsWith(uint codePoint) => Span.EndsWith(codePoint);
method TrySubstringFrom (line 172) | public bool TrySubstringFrom(Utf8Buffer value, out Utf8Buffer result)
method TrySubstringFrom (line 186) | public bool TrySubstringFrom(uint codePoint, out Utf8Buffer result)
method TrySubstringTo (line 200) | public bool TrySubstringTo(Utf8Buffer value, out Utf8Buffer result)
method TrySubstringTo (line 214) | public bool TrySubstringTo(uint codePoint, out Utf8Buffer result)
method Substring (line 233) | public Utf8Buffer Substring(int index) => index == 0 ? this : Substrin...
method Substring (line 235) | public Utf8Buffer Substring(int index, int length)
method IndexOf (line 246) | public int IndexOf(Utf8Buffer value) => Bytes.IndexOf(value.Bytes);
method IndexOf (line 248) | public int IndexOf(uint codePoint) => Span.IndexOf(codePoint);
method IndexOf (line 250) | public int IndexOf(string s) => Span.IndexOf(new Utf8Span(Encoding.UTF...
method LastIndexOf (line 252) | public int LastIndexOf(Utf8Buffer value) => Span.LastIndexOf(value.Span);
method LastIndexOf (line 254) | public int LastIndexOf(uint codePoint) => Span.LastIndexOf(codePoint);
method TryFormat (line 256) | public bool TryFormat(Span<byte> buffer, out int written, StandardForm...
method Dispose (line 387) | private void Dispose(bool disposing)
FILE: jemalloc.Api/jemalloc.cs
class Jem (line 42) | public unsafe static partial class Jem
type __Internal (line 44) | public partial struct __Internal
method JeMalloc (line 46) | [SuppressUnmanagedCodeSecurity]
method JeCalloc (line 51) | [SuppressUnmanagedCodeSecurity]
method JePosixMemalign (line 56) | [SuppressUnmanagedCodeSecurity]
method JeAlignedAlloc (line 61) | [SuppressUnmanagedCodeSecurity]
method JeRealloc (line 66) | [SuppressUnmanagedCodeSecurity]
method JeFree (line 71) | [SuppressUnmanagedCodeSecurity]
method JeMallocx (line 76) | [SuppressUnmanagedCodeSecurity]
method JeRallocx (line 81) | [SuppressUnmanagedCodeSecurity]
method JeXallocx (line 86) | [SuppressUnmanagedCodeSecurity]
method JeSallocx (line 91) | [SuppressUnmanagedCodeSecurity]
method JeDallocx (line 96) | [SuppressUnmanagedCodeSecurity]
method JeSdallocx (line 101) | [SuppressUnmanagedCodeSecurity]
method JeNallocx (line 106) | [SuppressUnmanagedCodeSecurity]
method JeMallctl (line 111) | [SuppressUnmanagedCodeSecurity]
method JeMallctlnametomib (line 116) | [SuppressUnmanagedCodeSecurity]
method JeMallctlbymib (line 121) | [SuppressUnmanagedCodeSecurity]
method JeMallocStatsPrint (line 126) | [SuppressUnmanagedCodeSecurity]
method JeMallocUsableSize (line 131) | [SuppressUnmanagedCodeSecurity]
method JeSetMallocConf (line 139) | [SuppressUnmanagedCodeSecurity]
method JeGetMallocConf (line 144) | [SuppressUnmanagedCodeSecurity]
method JeGetMallocMessagePtr (line 149) | [SuppressUnmanagedCodeSecurity]
method JeSetMallocMessagePtr (line 153) | [SuppressUnmanagedCodeSecurity]
FILE: jemalloc.Benchmarks/BenchmarkStatisticColumn.cs
class BenchmarkStatisticColumn (line 13) | public class BenchmarkStatisticColumn : IColumn
method BenchmarkStatisticColumn (line 16) | public BenchmarkStatisticColumn(string columnName, string legend)
method IsDefault (line 51) | public bool IsDefault(Summary summary, Benchmark benchmark) => false;
method GetValue (line 53) | public string GetValue(Summary summary, Benchmark benchmark)
method IsAvailable (line 79) | public bool IsAvailable(Summary summary)
method GetValue (line 91) | public string GetValue(Summary summary, Benchmark benchmark, ISummaryS...
method ToString (line 97) | public override string ToString() => ColumnName;
FILE: jemalloc.Benchmarks/Benchmarks/FixedBufferVsManagedArray.cs
class FixedBufferVsManagedArrayBenchmark (line 11) | [OrderProvider(methodOrderPolicy: MethodOrderPolicy.Declared)]
method GlobalSetup (line 20) | public override void GlobalSetup()
method FillManagedArray (line 48) | [Benchmark(Description = "Fill a managed array with a single value.")]
method FillFixedBuffer (line 60) | [Benchmark(Description = "Fill a FixedBuffer on the system unmanaged h...
method FillManagedArrayWithCreate (line 69) | [Benchmark(Description = "Create and Fill a managed array with a singl...
method FillFixedBufferWithCreate (line 82) | [Benchmark(Description = "Create and Fill a FixedBuffer on the system ...
method FillValidateAndCleanup (line 92) | [GlobalCleanup(Target = nameof(FillFixedBuffer))]
method ArithmeticMutiplyManagedArray (line 118) | [Benchmark(Description = "Multiply all values of a managed array with ...
method ArithmeticMultiplyNativeArray (line 133) | [Benchmark(Description = "Vector multiply all values of a native array...
method ArithmeticMultiplyValidateAndCleanup (line 146) | [GlobalCleanup(Target = nameof(ArithmeticMultiplyNativeArray))]
method CreateManagedArray (line 182) | [BenchmarkCategory("Create")]
method CreateNativeArray (line 189) | [BenchmarkCategory("Create")]
FILE: jemalloc.Benchmarks/Benchmarks/HugeNativeVsManagedArray.cs
class HugeNativeVsManagedArrayBenchmark (line 10) | [OrderProvider(methodOrderPolicy: MethodOrderPolicy.Declared)]
method GlobalSetup (line 19) | public override void GlobalSetup()
method FillManagedArray (line 39) | [Benchmark(Description = "Fill a managed array with the maximum size [...
method FillHugeNativeArray (line 52) | [Benchmark(Description = "Fill a HugeArray on the system unmanaged hea...
method FillManagedArrayWithCreate (line 62) | [Benchmark(Description = "Create and Fill a managed array with a singl...
method FillHugeNativeArrayWithCreate (line 76) | [Benchmark(Description = "Create and Fill a HugeArray on the system un...
method CleanupFillArray (line 88) | [GlobalCleanup(Target = nameof(FillHugeNativeArray))]
method CreateManagedArray (line 110) | [BenchmarkCategory("Create")]
method CreateHugeNativeArray (line 117) | [BenchmarkCategory("Create")]
FILE: jemalloc.Benchmarks/Benchmarks/MallocVsArray.cs
class MallocVsArrayBenchmark (line 11) | [OrderProvider(methodOrderPolicy: MethodOrderPolicy.Declared)]
method GlobalSetup (line 20) | public override void GlobalSetup()
method CreateManagedArray (line 27) | [Benchmark(Description = "Create array of data on the managed heap.")]
method CreateSpan (line 36) | [Benchmark(Description = "Malloc buffer and Span<T> on the system mana...
method FillManagedArray (line 52) | [Benchmark(Description = "Fill array of data on the managed heap.")]
method FillSpan (line 65) | [Benchmark(Description = "Fill memory on the system unmanaged heap usi...
method FragmentLOHBaseline (line 80) | [Benchmark(Description = "Run an allocation pattern that won't fragmen...
method FragmentLOH (line 110) | [Benchmark(Description = "Run an allocation pattern that fragments the...
method FragmentLOHWithCompact (line 145) | [Benchmark(Description = "Run an allocation pattern that fragments the...
method FragmentNativeHeapBaseline (line 185) | [Benchmark(Description = "Run an allocation pattern that won't fragmen...
method FragmentNativeHeap (line 229) | [Benchmark(Description = "Run an allocation pattern that fragments the...
FILE: jemalloc.Benchmarks/Benchmarks/SafeVsManagedArray.cs
class SafeVsManagedArrayBenchmark (line 11) | [OrderProvider(methodOrderPolicy: MethodOrderPolicy.Declared)]
method GlobalSetup (line 18) | public override void GlobalSetup()
method FillManagedArray (line 44) | [Benchmark(Description = "Fill a managed array with a single value.")]
method FillNativeArray (line 57) | [Benchmark(Description = "Fill a SafeArray on the system unmanaged hea...
method FillManagedArrayWithCreate (line 67) | [Benchmark(Description = "Create and Fill a managed array with a singl...
method FillNativeArrayWithCreate (line 81) | [Benchmark(Description = "Create and Fill a SafeArray on the system un...
method FillArrayValidateAndCleanup (line 92) | [GlobalCleanup(Target = nameof(FillNativeArrayWithCreate))]
method ArithmeticMutiplyManagedArray (line 114) | [Benchmark(Description = "Multiply all values of a managed array with ...
method ArithmeticMultiplyNativeArray (line 128) | [Benchmark(Description = "Vector multiply all values of a native array...
method ArithmeticMultiplyValidateAndCleanup (line 139) | [GlobalCleanup(Target = nameof(ArithmeticMultiplyNativeArray))]
FILE: jemalloc.Benchmarks/Benchmarks/Vector.cs
class VectorBenchmark (line 16) | [OrderProvider(methodOrderPolicy: MethodOrderPolicy.Declared)]
method MandelbrotSetup (line 34) | [GlobalSetup(Target = nameof(MandelbrotManaged))]
method MandelbrotManaged (line 57) | [Benchmark(Description = "Create Mandelbrot plot bitmap single-threade...
method MandelbrotUnmanagedv1 (line 70) | [Benchmark(Description = "Create Mandelbrot plot bitmap single-threade...
method MandelbrotManagedv4 (line 111) | [Benchmark(Description = "Create Mandelbrot plot bitmap multi-threaded...
method MandelbrotUnmanagedv2 (line 125) | [Benchmark(Description = "Create Mandelbrot plot bitmap single-threade...
method MandelbrotManagedv5 (line 140) | [Benchmark(Description = "Create Mandelbrot plot bitmap single-threade...
method MandelbrotManagedv3 (line 154) | [Benchmark(Description = "Create Mandelbrot plot bitmap single-threade...
method MandelbrotManagedv6 (line 167) | [Benchmark(Description = "Create Mandelbrot plot bitmap multi-threaded...
method MandelbrotManagedv7 (line 181) | [Benchmark(Description = "Create Mandelbrot plot bitmap single-threade...
method MandelbrotManagedv8 (line 194) | [Benchmark(Description = "Create Mandelbrot plot bitmap multi-threaded...
method MandelbrotUnmanagedv3 (line 207) | [Benchmark(Description = "Create Mandelbrot plot bitmap single-threade...
method MandelbrotUnmanagedv5 (line 220) | [Benchmark(Description = "Create Mandelbrot plot bitmap single-threade...
method MandelbrotUnmanagedv4 (line 233) | [Benchmark(Description = "Create Mandelbrot plot bitmap multi-threaded...
method MandelbrotValidateAndCleanup (line 247) | [GlobalCleanup(Target = nameof(MandelbrotUnmanagedv4))]
method _FillGlobalSetup (line 394) | [GlobalSetup(Target = nameof(FillManagedArray))]
method FillManagedArray (line 407) | [Benchmark(Description = "Serial fill managed memory array.")]
method FillManagedArrayUsingVector (line 415) | [Benchmark(Description = "Vector fill managed memory array.")]
method FillUnmanagedArray (line 428) | [Benchmark(Description = "Vector fill unmanaged memory array.")]
method _FillGlobalValidateAndCleanup (line 437) | [GlobalCleanup(Target = nameof(FillUnmanagedArray))]
method TestGlobalSetup (line 451) | [GlobalSetup(Target = nameof(TestManagedArrayLessThan))]
method TestManagedArrayLessThan (line 467) | [Benchmark(Description = "Serial test managed memory array less than.")]
method TestVectorManagedArrayLessThan (line 477) | [Benchmark(Description = "Vector test managed memory array less than.")]
method TestNativeArrayLessThan (line 520) | [Benchmark(Description = "Vector test native array less than.")]
method _TestGlobalValidateAndCleanup (line 531) | [GlobalCleanup(Target = nameof(TestNativeArrayLessThan))]
method _MandelbrotManagedv0 (line 562) | private byte[] _MandelbrotManagedv0(ref byte[] output)
method _MandelbrotManagedv1 (line 584) | private byte[] _MandelbrotManagedv1(ref byte[] output)
method _MandelbrotManagedv2 (line 622) | private unsafe byte[] _MandelbrotManagedv2()
method _MandelbrotManagedv3 (line 682) | private int[] _MandelbrotManagedv3(ref int[] output)
method _MandelbrotManagedv4 (line 725) | private int[] _MandelbrotManagedv4()
method _MandelbrotManagedv5 (line 766) | private unsafe int[] _MandelbrotManagedv5(ref int[] output)
method _MandelbrotManagedv6 (line 803) | private int[] _MandelbrotManagedv6()
method _MandelbrotManagedv7 (line 846) | private unsafe int[] _MandelbrotManagedv7(ref int[] output)
method _MandelbrotManagedv8 (line 888) | private int[] _MandelbrotManagedv8()
method _MandelbrotUnmanagedv1 (line 915) | private FixedBuffer<byte> _MandelbrotUnmanagedv1(ref FixedBuffer<byte>...
method _MandelbrotUnmanagedv2 (line 949) | private FixedBuffer<int> _MandelbrotUnmanagedv2(ref FixedBuffer<int> o...
method _MandelbrotUnmanagedv3 (line 997) | private FixedBuffer<int> _MandelbrotUnmanagedv3(ref FixedBuffer<int> o...
method _MandelbrotUnmanagedv4 (line 1025) | private unsafe void _MandelbrotUnmanagedv4(FixedBuffer<int> output)
method _MandelbrotUnmanagedv5 (line 1053) | private unsafe void _MandelbrotUnmanagedv5(ref FixedBuffer<int> output)
method GetByte (line 1082) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method GetByte (line 1102) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method GetByte (line 1119) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method SquareAbs (line 1145) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method WriteMandelbrotPPM (line 1151) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method WriteMandelbrotPPM (line 1174) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method WriteMandelbrotPPM (line 1197) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method MandelbrotBitmapLocation (line 1219) | public IEnumerable<ValueTuple<int, int>> MandelbrotBitmapLocation(int j)
method GetISPCBaselineResult (line 1228) | public string GetISPCBaselineResult()
method GetISPCResult (line 1243) | public string GetISPCResult()
method GetISPCTasksResult (line 1258) | public string GetISPCTasksResult()
method GetISPCResult2 (line 1273) | public string GetISPCResult2()
method GetISPCTasksResult2 (line 1289) | public string GetISPCTasksResult2()
FILE: jemalloc.Benchmarks/JemBenchmark.cs
type Category (line 21) | public enum Category
type Operation (line 30) | public enum Operation
class JemBenchmark (line 41) | [JemBenchmarkJob]
method JemBenchmark (line 46) | static JemBenchmark()
method JemBenchmark (line 50) | public JemBenchmark()
method GetParameters (line 96) | public IEnumerable<IParam> GetParameters()
method GetBenchmarkMethodCount (line 102) | public static int GetBenchmarkMethodCount<TBench>() where TBench : Jem...
method GlobalSetup (line 107) | [GlobalSetup]
method SetColdStartOverride (line 116) | public static void SetColdStartOverride(bool value)
method SetTargetCountOverride (line 121) | public static void SetTargetCountOverride(int value)
method SetInvocationCountOverride (line 126) | public static void SetInvocationCountOverride(int value)
method SetWarmupCountOverride (line 131) | public static void SetWarmupCountOverride(int value)
method GetValue (line 136) | public TValue GetValue<TValue>(string name, [CallerMemberName] string ...
method SetValue (line 145) | public void SetValue<TValue>(string name, TValue value, [CallerMemberN...
method RemoveValue (line 151) | public void RemoveValue(string name, [CallerMemberName] string memberN...
method SetStatistic (line 156) | public void SetStatistic(string name, string value, [CallerMemberName]...
method SetMemoryStatistics (line 161) | public void SetMemoryStatistics([CallerMemberName] string memberName =...
method Info (line 171) | public static void Info(string format, params object[] values) => Log....
method DebugInfo (line 173) | public static void DebugInfo(string format, params object[] values)
method InfoThis (line 181) | public static void InfoThis([CallerMemberName] string memberName = "",...
method DebugInfoThis (line 183) | public static void DebugInfoThis([CallerMemberName] string memberName ...
method Error (line 191) | public static void Error(string text, [CallerMemberName] string member...
method Error (line 194) | public static void Error(string format, params object[] values) => Log...
method PrintBytes (line 197) | public static string PrintBytes(double bytes, string suffix = "")
method PrintBytesToTuple (line 219) | public static Tuple<double, string> PrintBytesToTuple(double bytes, st...
FILE: jemalloc.Benchmarks/JemBenchmarkAttribute.cs
class JemBenchmarkAttribute (line 11) | public class JemBenchmarkAttribute : BenchmarkAttribute
FILE: jemalloc.Benchmarks/JemBenchmarkJobAttribute.cs
class JemBenchmarkJobAttribute (line 14) | [AttributeUsage(AttributeTargets.Class | AttributeTargets.Assembly, Allo...
method JemBenchmarkJobAttribute (line 17) | public JemBenchmarkJobAttribute(
FILE: jemalloc.Benchmarks/JemBenchmarkParam.cs
class JemBenchmarkParam (line 10) | public class JemBenchmarkParam<T> : IParam where T : struct
method JemBenchmarkParam (line 16) | public JemBenchmarkParam(T value) => this.value = value;
method ToSourceCode (line 22) | public string ToSourceCode() => $"new {ctorName}({value})";
FILE: jemalloc.Benchmarks/JemStatisticColumn.cs
class JemStatisticColumn (line 12) | public class JemStatisticColumn : IColumn
method JemStatisticColumn (line 15) | public JemStatisticColumn(string columnName, Func<string> jemStatFunct...
method IsDefault (line 50) | public bool IsDefault(Summary summary, Benchmark benchmark) => false;
method GetValue (line 52) | public string GetValue(Summary summary, Benchmark benchmark) => JemSta...
method IsAvailable (line 54) | public bool IsAvailable(Summary summary) => Jem.Initialized;
method GetValue (line 58) | public string GetValue(Summary summary, Benchmark benchmark, ISummaryS...
method ToString (line 64) | public override string ToString() => ColumnName;
FILE: jemalloc.Benchmarks/ProcessStatisticColumn.cs
class ProcessStatisticColumn (line 12) | public class ProcessStatisticColumn : IColumn
method ProcessStatisticColumn (line 15) | public ProcessStatisticColumn(string columnName, Func<string> jemStatF...
method IsDefault (line 50) | public bool IsDefault(Summary summary, Benchmark benchmark) => false;
method GetValue (line 52) | public string GetValue(Summary summary, Benchmark benchmark) => JemSta...
method IsAvailable (line 54) | public bool IsAvailable(Summary summary) => Jem.Initialized;
method GetValue (line 58) | public string GetValue(Summary summary, Benchmark benchmark, ISummaryS...
method ToString (line 64) | public override string ToString() => ColumnName;
FILE: jemalloc.Benchmarks/TestUDT.cs
type TestUDT (line 7) | public struct TestUDT : IEquatable<TestUDT>, IComparable<TestUDT>, IConv...
method MakeTestRecord (line 17) | public static TestUDT MakeTestRecord(Random rng)
method Equals (line 34) | public bool Equals(TestUDT r)
method GetTypeCode (line 42) | public TypeCode GetTypeCode()
method ToBoolean (line 47) | bool IConvertible.ToBoolean(IFormatProvider provider)
method GetDoubleValue (line 52) | double GetDoubleValue()
method ToByte (line 57) | byte IConvertible.ToByte(IFormatProvider provider)
method ToChar (line 62) | char IConvertible.ToChar(IFormatProvider provider)
method ToDateTime (line 67) | DateTime IConvertible.ToDateTime(IFormatProvider provider)
method ToDecimal (line 72) | decimal IConvertible.ToDecimal(IFormatProvider provider)
method ToDouble (line 77) | double IConvertible.ToDouble(IFormatProvider provider)
method ToInt16 (line 82) | short IConvertible.ToInt16(IFormatProvider provider)
method ToInt32 (line 87) | int IConvertible.ToInt32(IFormatProvider provider)
method ToInt64 (line 92) | long IConvertible.ToInt64(IFormatProvider provider)
method ToSByte (line 97) | sbyte IConvertible.ToSByte(IFormatProvider provider)
method ToSingle (line 102) | float IConvertible.ToSingle(IFormatProvider provider)
method ToString (line 107) | string IConvertible.ToString(IFormatProvider provider)
method ToType (line 112) | object IConvertible.ToType(Type conversionType, IFormatProvider provider)
method ToUInt16 (line 117) | ushort IConvertible.ToUInt16(IFormatProvider provider)
method ToUInt32 (line 122) | uint IConvertible.ToUInt32(IFormatProvider provider)
method ToUInt64 (line 127) | ulong IConvertible.ToUInt64(IFormatProvider provider)
method CompareTo (line 134) | public int CompareTo(TestUDT other)
FILE: jemalloc.Bindings/JemallocLibrary.cs
class JemallocLibrary (line 14) | public class JemallocLibrary : ILibrary
method Setup (line 17) | public void Setup(Driver driver)
method SetupPasses (line 36) | public void SetupPasses(Driver driver)
method Preprocess (line 42) | public void Preprocess(Driver driver, ASTContext ctx)
method Postprocess (line 48) | public void Postprocess(Driver driver, ASTContext ctx)
FILE: jemalloc.Bindings/Program.cs
class Program (line 11) | class Program
method Main (line 13) | static void Main(string[] args)
FILE: jemalloc.Bindings/jemalloc-win-msvc.h
type extent_hooks_t (line 204) | typedef struct extent_hooks_s extent_hooks_t;
type extent_hooks_s (line 270) | struct extent_hooks_s {
FILE: jemalloc.Buffers/JemPinnable.cs
class JemPinnable (line 9) | [StructLayout(LayoutKind.Sequential)]
FILE: jemalloc.Buffers/NativeHelpers.cs
class NativeHelpers (line 15) | internal static partial class NativeHelpers
method IndexOf (line 17) | public static int IndexOf(ref byte searchSpace, int searchSpaceLength,...
method IndexOfAny (line 52) | public static int IndexOfAny(ref byte searchSpace, int searchSpaceLeng...
method IndexOf (line 72) | public static unsafe int IndexOf(ref byte searchSpace, byte value, int...
method IndexOfAny (line 186) | public static unsafe int IndexOfAny(ref byte searchSpace, byte value0,...
method IndexOfAny (line 320) | public static unsafe int IndexOfAny(ref byte searchSpace, byte value0,...
method SequenceEqual (line 459) | public static unsafe bool SequenceEqual(ref byte first, ref byte secon...
method LocateFirstFoundByte (line 519) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method LocateFirstFoundByte (line 541) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method GetVector (line 555) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method IndexOf (line 579) | public static int IndexOf<T>(ref T searchSpace, int searchSpaceLength,...
method IndexOf (line 615) | public static unsafe int IndexOf<T>(ref T searchSpace, T value, int le...
method SequenceEqual (line 689) | public static bool SequenceEqual<T>(ref T first, ref T second, int len...
method CopyTo (line 762) | public static unsafe void CopyTo<T>(ref T dst, int dstLength, ref T sr...
method Add (line 841) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method IsReferenceOrContainsReferences (line 868) | public static bool IsReferenceOrContainsReferences<T>() => PerTypeValues...
method IsReferenceOrContainsReferencesCore (line 870) | private static bool IsReferenceOrContainsReferencesCore(Type type)
class PerTypeValues (line 896) | public static class PerTypeValues<T>
method MeasureArrayAdjustment (line 909) | private static IntPtr MeasureArrayAdjustment()
method ClearLessThanPointerSized (line 916) | public unsafe static void ClearLessThanPointerSized(byte* ptr, UIntPtr b...
method ClearLessThanPointerSized (line 941) | public static unsafe void ClearLessThanPointerSized(ref byte b, UIntPtr ...
method ClearPointerSizedWithoutReferences (line 967) | public unsafe static void ClearPointerSizedWithoutReferences(ref byte b,...
method ClearPointerSizedWithReferences (line 1003) | public unsafe static void ClearPointerSizedWithReferences(ref IntPtr ip,...
method LessThanEqual (line 1041) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
type Reg64 (line 1049) | [StructLayout(LayoutKind.Sequential, Size = 64)]
type Reg32 (line 1051) | [StructLayout(LayoutKind.Sequential, Size = 32)]
type Reg16 (line 1053) | [StructLayout(LayoutKind.Sequential, Size = 16)]
FILE: jemalloc.Buffers/NativeMemory.cs
class NativeMemory (line 15) | public class NativeMemory<T> : OwnedMemory<T> where T : struct
method NativeMemory (line 18) | public NativeMemory(int length) : base()
method NativeMemory (line 28) | public NativeMemory(params T[] values) : this(values.Length)
method Retain (line 53) | public override void Retain()
method Release (line 65) | public override bool Release()
method Pin (line 87) | public override MemoryHandle Pin()
method TryGetArray (line 96) | protected override bool TryGetArray(out ArraySegment<T> arraySegment)
method AsTensor (line 109) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method AsVector (line 116) | [MethodImpl(MethodImplOptions.AggressiveInlining)]
method Allocate (line 137) | protected virtual IntPtr Allocate()
method OnNoReferences (line 144) | protected virtual void OnNoReferences() {}
method IsNumericType (line 147) | protected bool IsNumericType()
method Dispose (line 214) | protected override void Dispose(bool disposing)
FILE: jemalloc.Cli/Options.cs
class Options (line 10) | class Options
class MallocBenchmarkOptions (line 53) | [Verb("malloc", HelpText = "Benchmark native memory allocation using jem...
class FixedBufferBenchmarkOptions (line 69) | [Verb("buffer", HelpText = "Benchmark FixedBuffer arrays backed by nativ...
class SafeArrayBenchmarkOptions (line 85) | [Verb("safe", HelpText = "Benchmark SafeArray arrays backed by native me...
class HugeNativeArrayBenchmarkOptions (line 101) | [Verb("huge", HelpText = "Benchmark HugeArray arrays backed by native me...
class VectorBenchmarkOptions (line 114) | [Verb("vector", HelpText = "Benchmark SIMD vectorized algorithms on nati...
FILE: jemalloc.Cli/Program.cs
class Program (line 19) | class Program
type ExitResult (line 21) | public enum ExitResult
method Main (line 35) | static void Main(string[] args)
method Benchmark (line 269) | static void Benchmark(Options o)
method Benchmark (line 324) | static void Benchmark<T>() where T : struct, IEquatable<T>, IComparabl...
method Exit (line 526) | static void Exit(ExitResult result)
method ExitWithCode (line 533) | static int ExitWithCode(ExitResult result)
method GetAutoBuiltHelpText (line 539) | static HelpText GetAutoBuiltHelpText(ParserResult<object> result)
method CurrentDomain_UnhandledException (line 552) | private static void CurrentDomain_UnhandledException(object sender, Un...
FILE: jemalloc.Examples/TestUDT.cs
type TestUDT (line 6) | public struct TestUDT : IEquatable<TestUDT>, IComparable<TestUDT>, IConv...
method MakeTestRecord (line 16) | public static TestUDT MakeTestRecord(Random rng)
method Equals (line 33) | public bool Equals(TestUDT r)
method GetTypeCode (line 41) | public TypeCode GetTypeCode()
method ToBoolean (line 46) | bool IConvertible.ToBoolean(IFormatProvider provider)
method GetDoubleValue (line 51) | double GetDoubleValue()
method ToByte (line 56) | byte IConvertible.ToByte(IFormatProvider provider)
method ToChar (line 61) | char IConvertible.ToChar(IFormatProvider provider)
method ToDateTime (line 66) | DateTime IConvertible.ToDateTime(IFormatProvider provider)
method ToDecimal (line 71) | decimal IConvertible.ToDecimal(IFormatProvider provider)
method ToDouble (line 76) | double IConvertible.ToDouble(IFormatProvider provider)
method ToInt16 (line 81) | short IConvertible.ToInt16(IFormatProvider provider)
method ToInt32 (line 86) | int IConvertible.ToInt32(IFormatProvider provider)
method ToInt64 (line 91) | long IConvertible.ToInt64(IFormatProvider provider)
method ToSByte (line 96) | sbyte IConvertible.ToSByte(IFormatProvider provider)
method ToSingle (line 101) | float IConvertible.ToSingle(IFormatProvider provider)
method ToString (line 106) | string IConvertible.ToString(IFormatProvider provider)
method ToType (line 111) | object IConvertible.ToType(Type conversionType, IFormatProvider provider)
method ToUInt16 (line 116) | ushort IConvertible.ToUInt16(IFormatProvider provider)
method ToUInt32 (line 121) | uint IConvertible.ToUInt32(IFormatProvider provider)
method ToUInt64 (line 126) | ulong IConvertible.ToUInt64(IFormatProvider provider)
method CompareTo (line 133) | public int CompareTo(TestUDT other)
FILE: jemalloc.StressTests/FixedBufferStressTests.cs
class FixedBufferStressTests (line 6) | public class FixedBufferStressTests
method Test1 (line 8) | [Fact(DisplayName ="Can allocate fixed buffers")]
FILE: jemalloc.Tests/BufferTests.cs
class BufferTests (line 9) | public class BufferTests : jemallocTest
method CanConstructBuffer (line 11) | [Fact]
FILE: jemalloc.Tests/FixedBufferTests.cs
class FixedBufferTests (line 9) | public class FixedBufferTests : jemallocTest
method CanCreateFixedArray (line 11) | [Fact(DisplayName = "Can create a fixed buffer of bytes")]
method CanDeAllocateFixedArray (line 37) | [Fact(DisplayName = "Can deallocate a fixed buffer of bytes")]
FILE: jemalloc.Tests/HugeArrayTests.cs
class HugeArrayTests (line 10) | public class HugeArrayTests : jemallocTest
method CanConstructHugeArray (line 14) | [Fact(DisplayName = "Can construct huge array")]
method CanAssignToHugeArrayElements (line 25) | [Fact(DisplayName = "Can correctly assign to HugeArray elements")]
method CanConvertToVector (line 52) | [Fact(DisplayName = "Can convert to Vector")]
method CanFill (line 79) | [Fact(DisplayName = "Can correctly fill")]
FILE: jemalloc.Tests/MallCtlTests.cs
class MallCtlTests (line 7) | public class MallCtlTests : jemallocTest
method MallCtlTests (line 9) | public MallCtlTests() : base() {}
method CanReadMallCtlInt32 (line 10) | [Fact]
method CanReadMallCtlBool (line 16) | [Fact]
method CanReadMallCtlStr (line 23) | [Fact]
FILE: jemalloc.Tests/MallocConfTests.cs
class MallocConfTests (line 9) | public class MallocConfTests : jemallocTest
method MallocConfTests (line 11) | public MallocConfTests() : base() {}
method CanGetConf (line 13) | [Fact]
FILE: jemalloc.Tests/MallocMessageTests.cs
class MallocMessageTests (line 9) | public class MallocMessageTests : jemallocTest
method CanPrintMallocStats (line 11) | [Fact]
FILE: jemalloc.Tests/MallocTests.cs
class MallocTests (line 7) | public class MallocTests
method MallocTests (line 11) | public MallocTests() : base()
method CanMallocandFree (line 20) | [Fact]
FILE: jemalloc.Tests/SafeArrayTests.cs
class SafeArrayTests (line 7) | public class SafeArrayTests : jemallocTest
method CanConstructSafeArray (line 9) | [Fact(DisplayName = "Can construct SafeArray")]
method CanConvertToVector (line 28) | [Fact(DisplayName = "Can convert to Vector")]
method CanVectorizedMultiply (line 41) | [Fact]
FILE: jemalloc.Tests/UDTTests.cs
class UDTTests (line 10) | public class UDTTests : jemallocTest
method UDTTests (line 13) | public UDTTests()
method CanVectorize (line 22) | public void CanVectorize()
FILE: jemalloc.Tests/Utf8BufferTests.cs
class Utf8BufferTests (line 9) | public class Utf8BufferTests : jemallocTest
method CanConstructUtf8String (line 11) | [Fact(DisplayName = "Can construct Utf8Buffer")]
FILE: jemalloc.Tests/VectorTests.cs
class VectorTests (line 17) | public class VectorTests
method VectorTests (line 26) | public VectorTests()
method CanConstructVectors (line 31) | [Fact(DisplayName = "Buffer elements can be accessed as vector.")]
method CanVectorizeMandelbrotManaged (line 44) | [Fact(DisplayName = "Can correctly run Mandelbrot algorithm using Vect...
method CanVectorizeMandelbrotManaged5 (line 54) | [Fact(DisplayName = "Can correctly run Mandelbrot algorithm using Vect...
method CanVectorizeMandelbrotUnmanaged (line 65) | [Fact(DisplayName = "Can correctly run Mandelbrot algorithm using Vect...
method VectorizeMandelbrotManaged (line 78) | private int[] VectorizeMandelbrotManaged()
method Mandelbrotv1Unmanaged (line 118) | private FixedBuffer<int> Mandelbrotv1Unmanaged()
method WriteMandelbrotPPM (line 172) | private void WriteMandelbrotPPM(int[] output, string name)
method WriteMandelbrotPPM (line 195) | private void WriteMandelbrotPPM(byte[] output, string name)
method VectorDoubleMandelbrot (line 219) | private unsafe FixedBuffer<long> VectorDoubleMandelbrot()
method SquareAbs (line 279) | private Vector<double> SquareAbs(Vector<double> Vre, Vector<double> Vim)
method GetValue (line 284) | private unsafe Vector<long> GetValue(Vector<double> Cx, Vector<double>...
method _Mandelbrotv2Unmanaged (line 325) | private FixedBuffer<byte> _Mandelbrotv2Unmanaged(ref FixedBuffer<byte>...
method _MandelbrotManagedv4 (line 410) | private byte[] _MandelbrotManagedv4()
method _MandelbrotManagedv5 (line 498) | private unsafe int[] _MandelbrotManagedv5(ref int[] output)
method _MandelbrotUnmanagedv1 (line 576) | private FixedBuffer<byte> _MandelbrotUnmanagedv1(ref FixedBuffer<byte>...
FILE: jemalloc.Tests/jemallocTest.cs
class jemallocTest (line 10) | public abstract class jemallocTest
method jemallocTest (line 15) | public jemallocTest()
Condensed preview — 79 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (517K chars).
[
{
"path": ".gitattributes",
"chars": 2518,
"preview": "###############################################################################\n# Set default behavior to automatically "
},
{
"path": ".gitignore",
"chars": 4441,
"preview": "## Ignore Visual Studio temporary files, build results, and\n## files generated by popular Visual Studio add-ons.\n\n# User"
},
{
"path": ".gitmodules",
"chars": 89,
"preview": "[submodule \"jemalloc\"]\n\tpath = jemalloc\n\turl = https://github.com/allisterb/jemalloc.git\n"
},
{
"path": "LICENSE",
"chars": 1073,
"preview": "MIT License\n\nCopyright (c) 2017 Allister Beharry\n\nPermission is hereby granted, free of charge, to any person obtaining "
},
{
"path": "README.md",
"chars": 28613,
"preview": "# jemalloc.NET: A native memory manager for .NET\n\n Microsoft. All rights reserved.\n// Licensed under the MIT license. See LICENSE file in the project"
},
{
"path": "jemalloc.Api/jemalloc.Api.csproj",
"chars": 2791,
"preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n <PropertyGroup>\n <TargetFramework>netstandard2.0</TargetFramework>\n <Platform"
},
{
"path": "jemalloc.Api/jemalloc.cs",
"chars": 10790,
"preview": "using System;\nusing System.Runtime.ConstrainedExecution;\nusing System.Runtime.InteropServices;\nusing System.Security;\n\nn"
},
{
"path": "jemalloc.Benchmarks/BenchmarkStatisticColumn.cs",
"chars": 4543,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\n\nusing BenchmarkDotNet.Configs;\nu"
},
{
"path": "jemalloc.Benchmarks/Benchmarks/FixedBufferVsManagedArray.cs",
"chars": 7493,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Runtime.InteropServices;\n\nusing BenchmarkDotNet.Attributes"
},
{
"path": "jemalloc.Benchmarks/Benchmarks/HugeNativeVsManagedArray.cs",
"chars": 4621,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nusing BenchmarkDotNet.Attributes;\nusing BenchmarkDo"
},
{
"path": "jemalloc.Benchmarks/Benchmarks/MallocVsArray.cs",
"chars": 11811,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Runtime;\nusing System.Runtime.InteropServices;\n\nusing Benc"
},
{
"path": "jemalloc.Benchmarks/Benchmarks/SafeVsManagedArray.cs",
"chars": 6443,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Runtime.InteropServices;\nusing System.Threading;\nusing Ben"
},
{
"path": "jemalloc.Benchmarks/Benchmarks/Vector.cs",
"chars": 51623,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Numerics;\nusing System.Runtime.CompilerSe"
},
{
"path": "jemalloc.Benchmarks/Design.md",
"chars": 1215,
"preview": "## Catgeories\n\n1. Malloc: Benchmark low-level malloc operations and creating Span<Y>\n\n2. Arrays: Bench\n\n\n1. Allocate ui"
},
{
"path": "jemalloc.Benchmarks/JemBenchmark.cs",
"chars": 7906,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing System.Linq;\nusing System.Reflection;\nu"
},
{
"path": "jemalloc.Benchmarks/JemBenchmarkAttribute.cs",
"chars": 414,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nusing BenchmarkDotNet.Configs;\n\nusing BenchmarkDotN"
},
{
"path": "jemalloc.Benchmarks/JemBenchmarkJobAttribute.cs",
"chars": 2898,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nusing BenchmarkDotNet.Engines;\nusing BenchmarkDotNe"
},
{
"path": "jemalloc.Benchmarks/JemBenchmarkParam.cs",
"chars": 558,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nusing BenchmarkDotNet.Code;\nusing BenchmarkDotNet.P"
},
{
"path": "jemalloc.Benchmarks/JemStatisticColumn.cs",
"chars": 2895,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nusing BenchmarkDotNet.Configs;\nusing BenchmarkDotNe"
},
{
"path": "jemalloc.Benchmarks/ProcessStatisticColumn.cs",
"chars": 3060,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nusing BenchmarkDotNet.Configs;\nusing BenchmarkDotNe"
},
{
"path": "jemalloc.Benchmarks/TestUDT.cs",
"chars": 3832,
"preview": "using System;\nusing System.Collections.Generic;\n\n\nnamespace jemalloc.Benchmarks\n{\n public struct TestUDT : IEquatabl"
},
{
"path": "jemalloc.Benchmarks/jemalloc.Benchmarks.csproj",
"chars": 1667,
"preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n <PropertyGroup>\n <TargetFramework>netcoreapp2.0</TargetFramework>\n <Platform>"
},
{
"path": "jemalloc.Bindings/App.config",
"chars": 182,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n<configuration>\n <startup> \n <supportedRuntime version=\"v4.0\" sku=\".N"
},
{
"path": "jemalloc.Bindings/JemallocLibrary.cs",
"chars": 1759,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\n\nus"
},
{
"path": "jemalloc.Bindings/Program.cs",
"chars": 311,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Text;\nusing System.Threading.Tasks;\n\nus"
},
{
"path": "jemalloc.Bindings/Properties/AssemblyInfo.cs",
"chars": 1402,
"preview": "using System.Reflection;\nusing System.Runtime.CompilerServices;\nusing System.Runtime.InteropServices;\n\n// General Infor"
},
{
"path": "jemalloc.Bindings/jemalloc-win-msvc.h",
"chars": 9689,
"preview": "#define JEMALLOC_H_\nextern \"C\" {\n\n\n/* Defined if __attribute__((...)) syntax is supported. */\n/* #undef JEMALLOC_HAVE_AT"
},
{
"path": "jemalloc.Bindings/jemalloc.Bindings.csproj",
"chars": 5624,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<Project ToolsVersion=\"15.0\" xmlns=\"http://schemas.microsoft.com/developer/msbui"
},
{
"path": "jemalloc.Bindings/packages.config",
"chars": 252,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<packages>\n <package id=\"Baseclass.Contrib.Nuget.Output\" version=\"2.3.0\" target"
},
{
"path": "jemalloc.Buffers/JemPinnable.cs",
"chars": 274,
"preview": "using System;\nusing System.Diagnostics;\nusing System.Runtime.InteropServices;\nusing System.Collections.Generic;\nusing S"
},
{
"path": "jemalloc.Buffers/NativeHelpers.cs",
"chars": 44042,
"preview": "// Licensed to the .NET Foundation under one or more agreements.\n// The .NET Foundation licenses this file to you under "
},
{
"path": "jemalloc.Buffers/NativeMemory.cs",
"chars": 7534,
"preview": "using System;\nusing System.Buffers;\nusing System.Runtime.InteropServices;\nusing System.Diagnostics.Contracts;\nusing Sys"
},
{
"path": "jemalloc.Buffers/jemalloc.Buffers.csproj",
"chars": 1390,
"preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n <PropertyGroup>\n <TargetFramework>netcoreapp2.0</TargetFramework>\n <Platforms"
},
{
"path": "jemalloc.Cli/Options.cs",
"chars": 6154,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nusing CommandLine;\nusing CommandLine.Text;\n\nnamespa"
},
{
"path": "jemalloc.Cli/Program.cs",
"chars": 28481,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Diagnostics.Contracts;\nusing System.Linq;\nusing System.Ref"
},
{
"path": "jemalloc.Cli/Properties/PublishProfiles/ReleaseProfile.pubxml",
"chars": 630,
"preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!--\nThis file is used by the publish/package process of your project. You can c"
},
{
"path": "jemalloc.Cli/jemalloc.Cli.csproj",
"chars": 2049,
"preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n <PropertyGroup>\n <OutputType>Exe</OutputType>\n <TargetFramework>netcoreapp2.0"
},
{
"path": "jemalloc.Examples/TestUDT.cs",
"chars": 3868,
"preview": "using System;\nusing System.Collections.Generic;\n\nnamespace jemalloc.Examples\n{\n public struct TestUDT : IEquatable<T"
},
{
"path": "jemalloc.Examples/jemalloc.Examples.csproj",
"chars": 420,
"preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n <PropertyGroup>\n <TargetFramework>netstandard2.0</TargetFramework>\n </PropertyG"
},
{
"path": "jemalloc.NET.sln",
"chars": 25031,
"preview": "\nMicrosoft Visual Studio Solution File, Format Version 12.00\n# Visual Studio 15\nVisualStudioVersion = 15.0.27130.0\nMini"
},
{
"path": "jemalloc.StressTests/FixedBufferStressTests.cs",
"chars": 670,
"preview": "using System;\nusing Xunit;\n\nnamespace jemalloc.StressTests\n{\n public class FixedBufferStressTests\n {\n [Fact"
},
{
"path": "jemalloc.StressTests/jemalloc.StressTests.csproj",
"chars": 759,
"preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n <PropertyGroup>\n <TargetFramework>netcoreapp2.0</TargetFramework>\n\n <IsPackab"
},
{
"path": "jemalloc.Tests/BufferTests.cs",
"chars": 390,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nusing Xunit;\n\nnamespace jemalloc.Tests\n{\n public"
},
{
"path": "jemalloc.Tests/FixedBufferTests.cs",
"chars": 2069,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nusing Xunit;\n\nnamespace jemalloc.Tests\n{\n public"
},
{
"path": "jemalloc.Tests/HugeArrayTests.cs",
"chars": 3001,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Linq;\nusing System.Numerics;\n\nusing Xunit;\n\nnamespace jema"
},
{
"path": "jemalloc.Tests/MallCtlTests.cs",
"chars": 669,
"preview": "using System;\nusing System.Diagnostics;\nusing Xunit;\n\nnamespace jemalloc.Tests\n{\n public class MallCtlTests : jemall"
},
{
"path": "jemalloc.Tests/MallocConfTests.cs",
"chars": 354,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nusing Xunit;\n\nnamespace jemalloc.Tests\n{\n public"
},
{
"path": "jemalloc.Tests/MallocMessageTests.cs",
"chars": 316,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nusing Xunit;\n\nnamespace jemalloc.Tests\n{\n public"
},
{
"path": "jemalloc.Tests/MallocTests.cs",
"chars": 1497,
"preview": "using System;\nusing System.Diagnostics;\nusing Xunit;\n\nnamespace jemalloc.Tests\n{\n public class MallocTests\n {\n "
},
{
"path": "jemalloc.Tests/SafeArrayTests.cs",
"chars": 1779,
"preview": "using System;\nusing System.Numerics;\n\nusing Xunit;\nnamespace jemalloc.Tests\n{\n public class SafeArrayTests : jemallo"
},
{
"path": "jemalloc.Tests/UDTTests.cs",
"chars": 875,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Buffers;\nusing System.Text;\n\nusing jemalloc.Examples;\n\nnam"
},
{
"path": "jemalloc.Tests/Utf8BufferTests.cs",
"chars": 397,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Text;\n\nusing Xunit;\n\nnamespace jemalloc.Tests\n{\n public"
},
{
"path": "jemalloc.Tests/VectorTests.cs",
"chars": 24078,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.IO;\nusing System.Linq;\nusing System.Numerics;\nusing System"
},
{
"path": "jemalloc.Tests/jemalloc.Tests.csproj",
"chars": 1280,
"preview": "<Project Sdk=\"Microsoft.NET.Sdk\">\n\n <PropertyGroup>\n <TargetFramework>netcoreapp2.0</TargetFramework>\n\n <IsPackab"
},
{
"path": "jemalloc.Tests/jemallocTest.cs",
"chars": 1023,
"preview": "using System;\nusing System.Collections.Generic;\nusing System.Diagnostics;\nusing System.Text;\n\nusing Xunit;\n\nnamespace j"
},
{
"path": "jembench.cmd",
"chars": 69,
"preview": "@echo off\ndotnet .\\x64\\Release\\netcoreapp2.0\\jemalloc.Cli.dll %*\n:end"
}
]
About this extraction
This page contains the full source code of the allisterb/jemalloc.NET GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 79 files (484.1 KB), approximately 116.8k tokens, and a symbol index with 645 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.