You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							139 lines
						
					
					
						
							3.9 KiB
						
					
					
				
			
		
		
		
			
			
			
		
		
	
	
							139 lines
						
					
					
						
							3.9 KiB
						
					
					
				| package integration | |
| 
 | |
| import ( | |
| 	"fmt" | |
| 	"sync" | |
| 	"sync/atomic" | |
| 	"testing" | |
| 	"time" | |
| 
 | |
| 	"github.com/seaweedfs/seaweedfs/weed/glog" | |
| ) | |
| 
 | |
| // TestQuickPerformance_10K tests the fixed broker with 10K records | |
| func TestQuickPerformance_10K(t *testing.T) { | |
| 	const ( | |
| 		totalRecords  = 10000 // 10K records for quick test | |
| 		numPartitions = int32(4) | |
| 		numProducers  = 4 | |
| 		brokerAddr    = "localhost:17777" | |
| 	) | |
| 
 | |
| 	// Create direct broker client | |
| 	client, err := NewDirectBrokerClient(brokerAddr) | |
| 	if err != nil { | |
| 		t.Fatalf("Failed to create direct broker client: %v", err) | |
| 	} | |
| 	defer client.Close() | |
| 
 | |
| 	topicName := fmt.Sprintf("quick-test-%d", time.Now().Unix()) | |
| 
 | |
| 	// Create topic | |
| 	glog.Infof("Creating topic %s with %d partitions", topicName, numPartitions) | |
| 	err = client.ConfigureTopic(topicName, numPartitions) | |
| 	if err != nil { | |
| 		t.Fatalf("Failed to configure topic: %v", err) | |
| 	} | |
| 
 | |
| 	// Performance tracking | |
| 	var totalProduced int64 | |
| 	var totalErrors int64 | |
| 	startTime := time.Now() | |
| 
 | |
| 	// Producer function | |
| 	producer := func(producerID int, recordsPerProducer int) error { | |
| 		for i := 0; i < recordsPerProducer; i++ { | |
| 			recordID := producerID*recordsPerProducer + i | |
| 
 | |
| 			// Generate test record | |
| 			testRecord := GenerateMockTestRecord(recordID) | |
| 			key, value := SerializeMockTestRecord(testRecord) | |
| 
 | |
| 			partition := int32(testRecord.UserID % int64(numPartitions)) | |
| 
 | |
| 			// Produce the record (now async!) | |
| 			err := client.PublishRecord(topicName, partition, key, value) | |
| 			if err != nil { | |
| 				atomic.AddInt64(&totalErrors, 1) | |
| 				if atomic.LoadInt64(&totalErrors) < 5 { | |
| 					glog.Errorf("Producer %d failed to produce record %d: %v", producerID, recordID, err) | |
| 				} | |
| 				continue | |
| 			} | |
| 
 | |
| 			atomic.AddInt64(&totalProduced, 1) | |
| 
 | |
| 			// Log progress | |
| 			if (i+1)%1000 == 0 { | |
| 				elapsed := time.Since(startTime) | |
| 				rate := float64(atomic.LoadInt64(&totalProduced)) / elapsed.Seconds() | |
| 				glog.Infof("Producer %d: %d records, current rate: %.0f records/sec", | |
| 					producerID, i+1, rate) | |
| 			} | |
| 		} | |
| 		return nil | |
| 	} | |
| 
 | |
| 	// Start concurrent producers | |
| 	glog.Infof("Starting %d producers for %d records total", numProducers, totalRecords) | |
| 
 | |
| 	var wg sync.WaitGroup | |
| 	recordsPerProducer := totalRecords / numProducers | |
| 
 | |
| 	for i := 0; i < numProducers; i++ { | |
| 		wg.Add(1) | |
| 		go func(producerID int) { | |
| 			defer wg.Done() | |
| 			if err := producer(producerID, recordsPerProducer); err != nil { | |
| 				glog.Errorf("Producer %d failed: %v", producerID, err) | |
| 			} | |
| 		}(i) | |
| 	} | |
| 
 | |
| 	// Wait for completion | |
| 	wg.Wait() | |
| 
 | |
| 	produceTime := time.Since(startTime) | |
| 	finalProduced := atomic.LoadInt64(&totalProduced) | |
| 	finalErrors := atomic.LoadInt64(&totalErrors) | |
| 
 | |
| 	// Performance results | |
| 	throughputPerSec := float64(finalProduced) / produceTime.Seconds() | |
| 	dataVolumeMB := float64(finalProduced) * 300 / (1024 * 1024) // ~300 bytes per record | |
| 	throughputMBPerSec := dataVolumeMB / produceTime.Seconds() | |
| 
 | |
| 	glog.Infof("\n"+ | |
| 		"QUICK PERFORMANCE TEST RESULTS\n"+ | |
| 		"=====================================\n"+ | |
| 		"Records produced: %d / %d\n"+ | |
| 		"Production time: %v\n"+ | |
| 		"Throughput: %.0f records/sec\n"+ | |
| 		"Data volume: %.1f MB\n"+ | |
| 		"Bandwidth: %.1f MB/sec\n"+ | |
| 		"Errors: %d (%.2f%%)\n"+ | |
| 		"Success rate: %.1f%%\n", | |
| 		finalProduced, totalRecords, | |
| 		produceTime, | |
| 		throughputPerSec, | |
| 		dataVolumeMB, | |
| 		throughputMBPerSec, | |
| 		finalErrors, | |
| 		float64(finalErrors)/float64(totalRecords)*100, | |
| 		float64(finalProduced)/float64(totalRecords)*100, | |
| 	) | |
| 
 | |
| 	// Assertions | |
| 	if finalProduced < int64(totalRecords*0.90) { // Allow 10% tolerance | |
| 		t.Errorf("Too few records produced: %d < %d (90%% of target)", finalProduced, int64(float64(totalRecords)*0.90)) | |
| 	} | |
| 
 | |
| 	if throughputPerSec < 100 { // Should be much higher than 1 record/sec now! | |
| 		t.Errorf("Throughput too low: %.0f records/sec (expected > 100)", throughputPerSec) | |
| 	} | |
| 
 | |
| 	if finalErrors > int64(totalRecords*0.10) { // Error rate should be < 10% | |
| 		t.Errorf("Too many errors: %d > %d (10%% of target)", finalErrors, int64(float64(totalRecords)*0.10)) | |
| 	} | |
| 
 | |
| 	glog.Infof("Performance test passed! Ready for million-record test.") | |
| }
 |