Repository: rclone/rclone
File: cmd/test/makefiles/speed.go (Go)

Code before:
	named directory which should be tidied up after.

	You can use the --json flag to only print the results in JSON format.`,
	Annotations: map[string]string{
		"versionIntroduced": "v1.72",
	},
	RunE: func(command *cobra.Command, args []string) error {
		ctx := command.Context()
		cmd.CheckArgs(1, 1, command, args)
		commonInit()

		// initial test
		size := fs.SizeSuffix(1024 * 1024)
		if !useJSON {
			fmt.Printf("Running initial test for 4 files of size %v\n", size)
		}
		stats, err := speedTest(ctx, 4, size, args[0])
		if err != nil {
			return fmt.Errorf("speed test failed: %w", err)
		}

		var results []*Stats

		// main tests
		for _, size := range []fs.SizeSuffix{small, medium, large} {
			combinedSpeed := stats.Upload.Speed + stats.Download.Speed
			numberOfFiles := int((float64(combinedSpeed) * time.Duration(testTime).Seconds()) / (2 * float64(size)))
			if !useJSON {
				fmt.Println()
				fmt.Println("number of files: ", numberOfFiles)
				if numberOfFiles < 1 {
					fmt.Printf("Skipping test for file size %v as too slow\n", size)
					continue
				} else if numberOfFiles > fcap {
					numberOfFiles = fcap
					fmt.Printf("Capping test for file size %v to %v files\n", size, fcap)
				}

				fmt.Printf("Running test for %v files of size %v\n", numberOfFiles, size)
				s, err := speedTest(ctx, numberOfFiles, size, args[0])
				if err != nil {
					return fmt.Errorf("speed test failed: %w", err)
				}
				results = append(results, s)

			} else {
				if numberOfFiles < 1 {
					continue
				} else if numberOfFiles > fcap {
					numberOfFiles = fcap
				}

Review comment (suggestion):
I don't think this calculation is quite right... Maybe this should be the average speed if the intention is that the total test for upload and download should hit the `testTime`?

It might be best to do the upload and download calculations separately as they are likely to be quite different.

Code after:
	Test time can be innaccurate with small file caps and large files. As it
	uses the results of an initial test to determine how many files to use in
	each subsequent test.

	It is recommended to use -q flag for a simpler output. e.g.:
	
	    rlone test speed remote: -q

	**NB** This command will create and delete files on the remote in a randomly
	named directory which should be tidied up after.

	You can use the --json flag to only print the results in JSON format.`,
	Annotations: map[string]string{
		"versionIntroduced": "v1.72",
	},
	RunE: func(command *cobra.Command, args []string) error {
		ctx := command.Context()
		cmd.CheckArgs(1, 1, command, args)
		commonInit()

		// initial test
		size := fs.SizeSuffix(1024 * 1024)
		logf("Running initial test for 4 files of size %v\n", size)
		stats, err := speedTest(ctx, 4, size, args[0])
		if err != nil {
			return fmt.Errorf("speed test failed: %w", err)
		}

		var results []*Stats

		// main tests
		logf("\nTest Time: %v, File cap: %d\n", testTime, fcap)
		for _, size := range []fs.SizeSuffix{small, medium, large} {
			numberOfFilesUpload := int((float64(stats.Upload.Speed) * time.Duration(testTime).Seconds()) / float64(size))
			numberOfFilesDownload := int((float64(stats.Download.Speed) * time.Duration(testTime).Seconds()) / float64(size))
			numberOfFiles := min(numberOfFilesUpload, numberOfFilesDownload)

			logf("\nNumber of files for upload and download: %v\n", numberOfFiles)
			if numberOfFiles < 1 {
				logf("Skipping test for file size %v as calculated number of files is 0\n", size)
				continue
			} else if numberOfFiles > fcap {
				numberOfFiles = fcap
				logf("Capping test for file size %v to %v files\n", size, fcap)
			}

			logf("Running test for %d files of size %v\n", numberOfFiles, size)
			s, err := speedTest(ctx, numberOfFiles, size, args[0])
			if err != nil {
				return fmt.Errorf("speed test failed: %w", err)
			}