Skip to content

Commit f8af6a1

Browse files
Added support for transactional workloads
1 parent 8d6a8c9 commit f8af6a1

File tree

5 files changed

+352
-397
lines changed

5 files changed

+352
-397
lines changed

README.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -184,12 +184,14 @@ You can override any setting in `config.yaml` using environment variables. This
184184
| `drop_collections` | `PERCONALOAD_DROP_COLLECTIONS` | Drop collections before starting (`true`/`false`) | `true` |
185185
| `skip_seed` | `PERCONALOAD_SKIP_SEED` | Do not seed initial data on start (`true`/`false`) | `true` |
186186
| `debug_mode` | `PERCONALOAD_DEBUG_MODE` | Enable verbose debug logging (`true`/`false`) | `false` |
187+
| `use_transactions` | `PERCONALOAD_USE_TRANSACTIONS` | Enable Transactional Workloads (`true`/`false`) | `false` |
187188
| **Operation Ratios** | | (Must sum to ~100) | |
188189
| `find_percent` | `PERCONALOAD_FIND_PERCENT` | Percentage of Find operations | `55` |
189190
| `insert_percent` | `PERCONALOAD_INSERT_PERCENT` | Percentage of Insert operations (this is not related to the initial seed inserts) | `20` |
190191
| `update_percent` | `PERCONALOAD_UPDATE_PERCENT` | Percentage of Update operations | `10` |
191192
| `delete_percent` | `PERCONALOAD_DELETE_PERCENT` | Percentage of Delete operations | `10` |
192193
| `aggregate_percent` | `PERCONALOAD_AGGREGATE_PERCENT` | Percentage of Aggregate operations | `5` |
194+
| `transaction_percent` | `PERCONALOAD_TRANSACTION_PERCENT` | Percentage of Transactional operations | `5` |
193195
| **Performance Optimization** | | | |
194196
| `find_batch_size` | `PERCONALOAD_FIND_BATCH_SIZE` | Documents returned per cursor batch | `100` |
195197
| `find_limit` | `PERCONALOAD_FIND_LIMIT` | Hard limit on documents per Find query | `10` |
@@ -303,6 +305,26 @@ export GOMAXPROCS=2
303305

304306
You can fine-tune plgm internal behavior by adjusting the parameters in `config.yaml`.
305307

308+
#### Workload Type
309+
By default, the tool comes preconfigured with the following workload distribution:
310+
311+
| Operation | Percentage |
312+
| :--- | :--- |
313+
| Find | 50% |
314+
| Update | 20% |
315+
| Delete | 10% |
316+
| Insert | 10% |
317+
| Aggregate | 5% |
318+
| Transaction | 5% |
319+
320+
You can modify any of the values above to run different types of workloads.
321+
322+
Please note:
323+
324+
* If `use_transactions: false`, the transaction_percent value is ignored.
325+
* If there are no aggregation queries defined in queries.json, the aggregate_percent value is also ignored.
326+
* Aggregate operations will only generate activity if at least one query with "operation": "aggregate" is defined in your active JSON query files.
327+
306328
#### Concurrency & Workers
307329
* **`concurrency`**: Controls the number of "Active Workers" continuously executing operations against the database.
308330
* *Tip:* Increase this to generate higher load. If set too high on a weak client, you may see increased client-side latency.

config.yaml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,14 +72,18 @@ concurrency: 4
7272
# Set to "0" to run the queries exactly once and exit.
7373
duration: "10s"
7474

75+
# Enable transactional workload
76+
use_transactions: false
77+
7578
# --- Operation Mix ---
7679
# The percentage of operations allocated to each type.
7780
# Will be normalized automatically if the sum != 100.
78-
find_percent: 55
81+
find_percent: 50
7982
update_percent: 20
8083
delete_percent: 10
8184
insert_percent: 10
8285
aggregate_percent: 5
86+
transaction_percent: 5
8387

8488
# Enable application-level debug
8589
debug_mode: false

internal/config/config.go

Lines changed: 35 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,9 @@ import (
99
)
1010

1111
// AppConfig holds the application's runtime configuration.
12-
// Struct tags: e.g.: when reading from YAML, the field named uri maps to URI in this struct
1312
type AppConfig struct {
1413
URI string `yaml:"uri"`
1514
// DefaultWorkload controls both file loading and generator logic.
16-
// True: Load only "default.json" and use custom workload logic (e.g. flights).
17-
// False: Load user files (excluding default.json) and use generic generator.
1815
DefaultWorkload bool `yaml:"default_workload"`
1916

2017
CollectionsPath string `yaml:"collections_path"`
@@ -24,13 +21,15 @@ type AppConfig struct {
2421
DocumentsCount int `yaml:"documents_count"`
2522
Concurrency int `yaml:"concurrency"`
2623

27-
Duration string `yaml:"duration"`
28-
FindPercent int `yaml:"find_percent"`
29-
UpdatePercent int `yaml:"update_percent"`
30-
DeletePercent int `yaml:"delete_percent"`
31-
InsertPercent int `yaml:"insert_percent"`
32-
AggregatePercent int `yaml:"aggregate_percent"`
33-
DebugMode bool `yaml:"debug_mode"`
24+
Duration string `yaml:"duration"`
25+
FindPercent int `yaml:"find_percent"`
26+
UpdatePercent int `yaml:"update_percent"`
27+
DeletePercent int `yaml:"delete_percent"`
28+
InsertPercent int `yaml:"insert_percent"`
29+
AggregatePercent int `yaml:"aggregate_percent"`
30+
TransactionPercent int `yaml:"transaction_percent"`
31+
UseTransactions bool `yaml:"use_transactions"`
32+
DebugMode bool `yaml:"debug_mode"`
3433

3534
FindBatchSize int `yaml:"find_batch_size"`
3635
FindLimit int64 `yaml:"find_limit"`
@@ -41,19 +40,14 @@ type AppConfig struct {
4140
RetryAttempts int `yaml:"retry_attempts"`
4241
RetryBackoffMs int `yaml:"retry_backoff_ms"`
4342

44-
// Typed struct view
45-
ConnectionParams ConnectionParams `yaml:"connection_params"`
46-
47-
// Raw/dynamic view
48-
CustomParamsMap map[string]interface{} `yaml:"custom_params"`
49-
50-
// Enable debugging
51-
Debug bool `yaml:"debug"`
43+
ConnectionParams ConnectionParams `yaml:"connection_params"`
44+
CustomParamsMap map[string]interface{} `yaml:"custom_params"`
45+
Debug bool `yaml:"debug"`
5246
}
5347

5448
type ConnectionParams struct {
5549
Username string `yaml:"username"`
56-
Password string `yaml:"-"` // Never load from YAML
50+
Password string `yaml:"-"`
5751
AuthSource string `yaml:"auth_source"`
5852
DirectConnection bool `yaml:"direct_connection"`
5953
ConnectionTimeout int `yaml:"connection_timeout"`
@@ -65,7 +59,6 @@ type ConnectionParams struct {
6559
ReadPreference string `yaml:"read_preference"`
6660
}
6761

68-
// LoadAppConfig reads the configuration from the specified path and applies environment variable overrides.
6962
func LoadAppConfig(path string) (*AppConfig, error) {
7063
b, err := os.ReadFile(path)
7164
if err != nil {
@@ -106,7 +99,6 @@ func applyDefaults(cfg *AppConfig) {
10699
if cfg.RetryBackoffMs <= 0 {
107100
cfg.RetryBackoffMs = 5
108101
}
109-
110102
}
111103

112104
func applyEnvOverrides(cfg *AppConfig) {
@@ -134,22 +126,14 @@ func applyEnvOverrides(cfg *AppConfig) {
134126
cfg.ConnectionParams.DirectConnection = b
135127
}
136128
}
137-
// Check if the environment variable is explicitly defined (even if empty)
138129
if v, exists := os.LookupEnv("PERCONALOAD_REPLICA_SET"); exists {
139130
cfg.ConnectionParams.ReplicaSetName = v
140131
}
141132
if v, exists := os.LookupEnv("PERCONALOAD_READ_PREFERENCE"); exists {
142133
cfg.ConnectionParams.ReadPreference = v
143134
}
144135

145-
// -------------------------------------------------------------------------
146-
// Custom Workload Logic:
147-
// If the user provides custom paths via environment variables, we infer
148-
// that they want to run a custom workload, so we force DefaultWorkload to false.
149-
// This overrides any previous setting (YAML or PERCONALOAD_DEFAULT_WORKLOAD).
150-
// -------------------------------------------------------------------------
151136
customWorkloadEnv := false
152-
153137
if envCollectionsPath := os.Getenv("PERCONALOAD_COLLECTIONS_PATH"); envCollectionsPath != "" {
154138
cfg.CollectionsPath = envCollectionsPath
155139
customWorkloadEnv = true
@@ -158,22 +142,25 @@ func applyEnvOverrides(cfg *AppConfig) {
158142
cfg.QueriesPath = envQueriesPath
159143
customWorkloadEnv = true
160144
}
161-
162145
if customWorkloadEnv {
163146
cfg.DefaultWorkload = false
164147
}
165-
// -------------------------------------------------------------------------
166148

167149
if envDrop := os.Getenv("PERCONALOAD_DROP_COLLECTIONS"); envDrop != "" {
168150
if b, err := strconv.ParseBool(envDrop); err == nil {
169151
cfg.DropCollections = b
170152
}
171153
}
172-
if envDrop := os.Getenv("PERCONALOAD_SKIP_SEED"); envDrop != "" {
173-
if b, err := strconv.ParseBool(envDrop); err == nil {
154+
if envSkip := os.Getenv("PERCONALOAD_SKIP_SEED"); envSkip != "" {
155+
if b, err := strconv.ParseBool(envSkip); err == nil {
174156
cfg.SkipSeed = b
175157
}
176158
}
159+
if envTx := os.Getenv("PERCONALOAD_USE_TRANSACTIONS"); envTx != "" {
160+
if b, err := strconv.ParseBool(envTx); err == nil {
161+
cfg.UseTransactions = b
162+
}
163+
}
177164
if envDocs := os.Getenv("PERCONALOAD_DOCUMENTS_COUNT"); envDocs != "" {
178165
if n, err := strconv.Atoi(envDocs); err == nil && n >= 0 {
179166
cfg.DocumentsCount = n
@@ -212,7 +199,12 @@ func applyEnvOverrides(cfg *AppConfig) {
212199
cfg.AggregatePercent = n
213200
}
214201
}
215-
// runtime optimization
202+
if p := os.Getenv("PERCONALOAD_TRANSACTION_PERCENT"); p != "" {
203+
if n, err := strconv.Atoi(p); err == nil && n >= 0 {
204+
cfg.TransactionPercent = n
205+
}
206+
}
207+
216208
if v := os.Getenv("PERCONALOAD_FIND_BATCH_SIZE"); v != "" {
217209
if n, err := strconv.Atoi(v); err == nil && n > 0 {
218210
cfg.FindBatchSize = n
@@ -251,20 +243,27 @@ func applyEnvOverrides(cfg *AppConfig) {
251243
}
252244

253245
func normalizePercentages(cfg *AppConfig) {
254-
total := cfg.FindPercent + cfg.UpdatePercent + cfg.DeletePercent + cfg.InsertPercent + cfg.AggregatePercent
246+
// If transactions are disabled, ignore their percentage entirely
247+
if !cfg.UseTransactions {
248+
cfg.TransactionPercent = 0
249+
}
250+
251+
total := cfg.FindPercent + cfg.UpdatePercent + cfg.DeletePercent + cfg.InsertPercent + cfg.AggregatePercent + cfg.TransactionPercent
255252
if total <= 0 {
256253
cfg.FindPercent = 100
257254
return
258255
}
256+
259257
if total != 100 {
260258
factor := 100.0 / float64(total)
261259
cfg.FindPercent = int(float64(cfg.FindPercent) * factor)
262260
cfg.UpdatePercent = int(float64(cfg.UpdatePercent) * factor)
263261
cfg.DeletePercent = int(float64(cfg.DeletePercent) * factor)
264262
cfg.InsertPercent = int(float64(cfg.InsertPercent) * factor)
265263
cfg.AggregatePercent = int(float64(cfg.AggregatePercent) * factor)
264+
cfg.TransactionPercent = int(float64(cfg.TransactionPercent) * factor)
266265

267-
finalTotal := cfg.FindPercent + cfg.UpdatePercent + cfg.DeletePercent + cfg.InsertPercent + cfg.AggregatePercent
266+
finalTotal := cfg.FindPercent + cfg.UpdatePercent + cfg.DeletePercent + cfg.InsertPercent + cfg.AggregatePercent + cfg.TransactionPercent
268267
if finalTotal != 100 {
269268
cfg.FindPercent += (100 - finalTotal)
270269
}

0 commit comments

Comments
 (0)