软件工程——数独 性能测试1
一、 开发环境
l Windows10 版本号1903
l RAM 16GB 3200MHz 三星
l AMD Ryzen 7 2700X 3.90GHz
l SSD 三星 MZVLB1TOHALR-00000
二、 文件读入
在进行测试的过程中发现1e6的数据读入大概需要300秒,远远高于写入的6秒钟。显然由于硬盘限制写入时间应该大于读入,因此文件读入代码必然是有问题的,时间是不可接受的。
原文件读入的代码如下:
- inline void mallocSudoku(Sudoku& s)
- {
- if (s == nullptr)
- {
- s = new int* [10];
- for (int i = 0; i < 10; i++)
- {
- s[i] = new int[10];
- }
- 10. }
11. }
- 12.
13. inline void freeSudoku(Sudoku& s)
14. {
- 15. if (s != nullptr)
- 16. {
- 17. for (int i = 0; i < 10; i++)
- 18. {
- 19. delete[] s[i];
- 20. }
- 21. delete[] s;
- 22. s = nullptr;
- 23. }
24. }
- 25.
26. inline void readLineFromFile(char* line)
27. {
- 28. char* tmp = new char;
- 29. DWORD num_bytes_read = 0;
- 30. for (int i = 0; i < 9; i++)//依据约定,一行最多有9个数字
- 31. {
- 32. *tmp = 0;
- 33. while (*tmp < '0' || *tmp > '9')
- 34. {
- 35. if (ReadFile(h_sudoku_problem_txt, tmp, 1, &num_bytes_read, NULL) && num_bytes_read == 0)
- 36. {
- 37. is_end = true;
- 38. return;
- 39. }
- 40. //num_bytes_read++;
- 41. }
- 42. line[i] = *tmp;
- 43. }
- 44. delete tmp;
45. }
- 46.
47. inline bool getSudokuFromFile(Sudoku s)
48. {
- 49. char* line = new char[9];
- 50. for (int i = 0; i < 9; i++)
- 51. {
- 52. readLineFromFile(line);
- 53. if (is_end)
- 54. return false;
- 55. for (int j = 0; j < 9; j++)
- 56. s[i + 1][j + 1] = line[j] - '0';
- 57. }
- 58.
- 59. delete[] line;
- 60. return true;
61. }
- 62.
63. //一次性读入一千个数独
64. inline void readSudoku()
65. {
- 66. for (int i = 0; i < BUFF_SIZE; i++)
- 67. {
- 68. Sudoku tmp = nullptr;
- 69. mallocSudoku(tmp);
- 70. if (getSudokuFromFile(tmp) == false)
- 71. {
- 72. freeSudoku(tmp);
- 73. return;
- 74. }
- 75. buff.push_back(tmp);
- 76. }
- 77. return;
- }
分析代码,不难发现问题所在,那就是调用一次ReadFile只读入了一个字节的数据。原代码主要是考虑到可能的数独文件格式问题,通过再次阅读问题要求,发现数独问题文件格式是固定的,因此可一次读入163个字节(与输出一致)。由于最后一个数独的后面没有空行,因此读入的数据是162个字节,由此可以作为结束判断。另外一方面,可以一次性读入多个数独进行分析。若读入字节数小于163的整数倍,则已读完。经过一系列测试,代码修改如下:
- inline void toSudoku(char* tmp, DWORD& n_bytes_read)
- {
- //由于读取时的限制,num_of_sudoku_in_buff <= BUFF_SIZE
- num_of_sudoku_in_buff = n_bytes_read / num_bytes_of_sudoku_infile;
- if (is_end)//因为结束时,向下取整,少了一个
- {
- num_of_sudoku_in_buff++;
- }
- for (int i = 0, j = 0; i < num_of_sudoku_in_buff; i++, j++)
- 10. {
- 11. Sudoku s = buff[i];
- 12. for (int row_idx = 1, col_idx = 1; j < (i + 1) * num_bytes_of_sudoku_infile - 1; j++, j++)
- 13. {
- 14. s[row_idx][col_idx++] = tmp[j] - '0';
- 15. if (col_idx == 10)
- 16. {
- 17. row_idx++;
- 18. col_idx = 1;
- 19. }
- 20. }
- 21. }
22. }
- 23.
24. //一次性读入一千个数独
25. inline void readSudoku()
26. {
- 27. char* tmp = new char[num_bytes_of_sudoku_infile * BUFF_SIZE + 10];
- 28. ReadFile(h_sudoku_problem_txt, tmp, num_bytes_of_sudoku_infile * BUFF_SIZE, &n_bytes_read, NULL);
- 29. if (num_bytes_of_sudoku_infile * BUFF_SIZE > n_bytes_read)
- 30. is_end = true;
- 31. toSudoku(tmp, n_bytes_read);
- 32. return;
- }
同时在文件读入修改中,将原先的vector更改为了数组形式,通过提前申请空间的方式减少了在获取数独和求解数独后释放数独空间的时间。
在只更改文件读入方式的情况下,时间从300秒降到了11秒,在将vector更改为数独数组之后,减少了new 和 delete的时间,又降低到了8秒钟。