or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

build-system.mdc-cpp-interoperability.mdcommand-line-tools.mdcore-language.mddebugging-profiling.mdimport-system.mdindex.mdipython-integration.md

debugging-profiling.mddocs/

0

# Debugging and Profiling

1

2

Cython provides comprehensive debugging and profiling capabilities for analyzing and optimizing Cython code. These tools enable source-level debugging, performance analysis, and identification of bottlenecks in compiled extensions.

3

4

## Capabilities

5

6

### Cython Debugger (cygdb)

7

8

GDB-based debugger that enables source-level debugging of both Python and Cython code.

9

10

```bash { .api }

11

cygdb [options] [path-to-project-directory] [gdb-args...]

12

13

Options:

14

--gdb-executable GDB GDB executable to use (default: gdb)

15

--verbose Verbose output

16

-h, --help Show help

17

18

Requirements:

19

- cython_debug/ directory with debug information

20

- Python executable compiled with debug symbols

21

- GDB with Python support

22

```

23

24

### Debug Build Configuration

25

26

Compiler directives and build options for debugging support.

27

28

```python { .api }

29

# Compilation options for debugging

30

compiler_directives = {

31

'linetrace': True, # Enable line tracing

32

'binding': True, # Enable function binding

33

'profile': True, # Enable profiling hooks

34

'emit_code_comments': True, # Add code comments in C output

35

}

36

37

# Build with debugging information

38

cythonize("module.pyx", gdb_debug=True, **compiler_directives)

39

```

40

41

### Profiling Integration

42

43

Integration with Python profiling tools and performance analysis.

44

45

```python { .api }

46

@cython.profile(True)

47

def profiled_function():

48

"""Function with profiling enabled."""

49

pass

50

51

@cython.linetrace(True)

52

@cython.binding(True)

53

def traced_function():

54

"""Function with line tracing for detailed profiling."""

55

pass

56

```

57

58

### Annotation and Performance Analysis

59

60

HTML annotation generation for performance analysis and optimization.

61

62

```bash { .api }

63

# Generate annotated HTML output

64

cython -a source.pyx # Basic annotation

65

cython -a --annotate-coverage coverage.xml source.pyx # With coverage data

66

67

# Via cythonize

68

cythonize --annotate source.pyx

69

```

70

71

## Usage Examples

72

73

### Setting Up Debug Environment

74

75

```python

76

# setup.py for debug builds

77

from setuptools import setup

78

from Cython.Build import cythonize

79

80

debug_args = {

81

'gdb_debug': True,

82

'compiler_directives': {

83

'linetrace': True,

84

'binding': True,

85

'profile': True,

86

'emit_code_comments': True,

87

'language_level': 3,

88

}

89

}

90

91

setup(

92

ext_modules=cythonize("src/*.pyx", **debug_args),

93

zip_safe=False,

94

)

95

```

96

97

### Basic Debugging Session

98

99

```bash

100

# 1. Build with debug information

101

python setup.py build_ext --inplace --debug

102

103

# 2. Start debugging session

104

cygdb

105

106

# 3. In GDB, set breakpoints and run

107

(gdb) cy break module.pyx:42

108

(gdb) cy run

109

(gdb) cy step

110

(gdb) cy print variable_name

111

(gdb) cy list

112

```

113

114

### Advanced Debugging Commands

115

116

```bash

117

# Cython-specific GDB commands

118

(gdb) cy break my_module.fast_function # Break at Cython function

119

(gdb) cy step # Step through Cython code

120

(gdb) cy next # Next line in Cython code

121

(gdb) cy print cython_var # Print Cython variable

122

(gdb) cy print local_vars # Print all local variables

123

(gdb) cy list # List current Cython source

124

(gdb) cy bt # Cython backtrace

125

(gdb) cy up # Move up Cython call stack

126

(gdb) cy down # Move down Cython call stack

127

```

128

129

### Debugging with IPython

130

131

```python

132

%load_ext cython

133

134

%%cython --gdb

135

def debug_function(int n):

136

cdef int i, total = 0

137

138

for i in range(n):

139

total += i * i # Breakpoint can be set here

140

141

return total

142

143

# Function is compiled with debug information

144

result = debug_function(100)

145

```

146

147

### Profiling with cProfile

148

149

```python

150

import cProfile

151

import pstats

152

153

# Enable profiling in Cython

154

%%cython -X profile=True -X linetrace=True -X binding=True

155

def slow_function(int n):

156

cdef int i, result = 0

157

for i in range(n):

158

result += expensive_operation(i)

159

return result

160

161

def expensive_operation(int x):

162

return x * x * x

163

164

# Profile the function

165

cProfile.run('slow_function(10000)', 'profile_stats')

166

167

# Analyze results

168

stats = pstats.Stats('profile_stats')

169

stats.sort_stats('cumulative')

170

stats.print_stats()

171

```

172

173

### Line-by-Line Profiling with line_profiler

174

175

```python

176

# Install: pip install line_profiler

177

178

%load_ext line_profiler

179

180

%%cython -X linetrace=True -X binding=True

181

@profile

182

def line_profiled_function(double[:] arr):

183

cdef int i

184

cdef double total = 0.0

185

cdef int n = arr.shape[0]

186

187

for i in range(n): # This line will be profiled

188

total += arr[i] * 2.0 # This line will be profiled

189

190

return total

191

192

# Run with line profiler

193

%lprun -f line_profiled_function line_profiled_function(data)

194

```

195

196

### Memory Profiling

197

198

```python

199

# Install: pip install memory_profiler

200

201

%load_ext memory_profiler

202

203

%%cython -X profile=True

204

@profile

205

def memory_intensive_function(int n):

206

cdef list data = []

207

cdef int i

208

209

for i in range(n):

210

data.append(i * i) # Memory allocation tracked

211

212

return sum(data)

213

214

# Profile memory usage

215

%mprun -f memory_intensive_function memory_intensive_function(100000)

216

```

217

218

### Annotation Analysis

219

220

```cython

221

# After running: cython -a my_module.pyx

222

# Open my_module.html in browser

223

224

%%cython -a

225

import numpy as np

226

cimport numpy as cnp

227

228

def analyze_performance(cnp.double_t[:] data):

229

"""Function to analyze with annotations."""

230

cdef int i

231

cdef double total = 0.0

232

cdef int n = data.shape[0]

233

234

# Yellow lines indicate Python interaction overhead

235

# White lines indicate pure C code

236

for i in range(n):

237

total += data[i] # Should be white (fast)

238

239

return total # May be yellow (Python object creation)

240

```

241

242

### Coverage-Based Annotation

243

244

```bash

245

# 1. Run tests with coverage

246

python -m pytest --cov=my_module --cov-report=xml

247

248

# 2. Generate annotated output with coverage data

249

cython -a --annotate-coverage coverage.xml my_module.pyx

250

251

# 3. View coverage-annotated HTML

252

# Green highlighting shows well-tested code

253

# Red highlighting shows untested code paths

254

```

255

256

### Debugging C Extensions

257

258

```python

259

# For debugging at the C level

260

%%cython --gdb -X emit_code_comments=True

261

def c_level_debug(int x):

262

cdef int* ptr = <int*>malloc(sizeof(int) * 10)

263

264

if ptr == NULL:

265

raise MemoryError("Failed to allocate memory")

266

267

ptr[0] = x # Can inspect C-level memory in GDB

268

269

cdef int result = ptr[0] * 2

270

free(ptr)

271

272

return result

273

```

274

275

### Performance Benchmarking

276

277

```python

278

import timeit

279

280

%%cython -X boundscheck=False -X wraparound=False -X cdivision=True

281

def optimized_function(double[:] data):

282

cdef int i

283

cdef double total = 0.0

284

cdef int n = data.shape[0]

285

286

for i in range(n):

287

total += data[i]

288

289

return total

290

291

# Benchmark against Python version

292

import numpy as np

293

data = np.random.random(1000000)

294

295

cython_time = timeit.timeit(

296

lambda: optimized_function(data),

297

number=100

298

)

299

300

python_time = timeit.timeit(

301

lambda: sum(data),

302

number=100

303

)

304

305

print(f"Cython: {cython_time:.4f}s")

306

print(f"Python: {python_time:.4f}s")

307

print(f"Speedup: {python_time/cython_time:.2f}x")

308

```

309

310

### Debugging Build Issues

311

312

```bash

313

# Verbose compilation for debugging build problems

314

cython --verbose my_module.pyx

315

316

# Generate intermediate C code for inspection

317

cython --output-file my_module.c my_module.pyx

318

319

# Check generated C code

320

less my_module.c

321

322

# Debug compilation errors

323

cython -Werror my_module.pyx # Treat warnings as errors

324

```

325

326

### Custom GDB Configuration

327

328

```bash

329

# Create .cygdbinit file for custom GDB commands

330

echo "set print pretty on" > .cygdbinit

331

echo "set pagination off" >> .cygdbinit

332

echo "define cy-locals" >> .cygdbinit

333

echo " cy print local_vars" >> .cygdbinit

334

echo "end" >> .cygdbinit

335

336

# Use custom configuration

337

cygdb --gdb-executable gdb-multiarch

338

```

339

340

### Integration with IDEs

341

342

```python

343

# VS Code configuration for Cython debugging

344

# In .vscode/launch.json:

345

{

346

"name": "Python: Cython Debug",

347

"type": "python",

348

"request": "launch",

349

"program": "${workspaceFolder}/test_script.py",

350

"console": "integratedTerminal",

351

"justMyCode": false,

352

"env": {

353

"CYTHON_DEBUG": "1"

354

}

355

}

356

```

357

358

The debugging and profiling capabilities in Cython provide comprehensive tools for analyzing performance bottlenecks, identifying optimization opportunities, and debugging both Python and C-level code in compiled extensions.