微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在函数中优化PHP中的大数组操作

如何解决在函数中优化PHP中的大数组操作

我想在函数内部修改一个大数组,所以我很确定我需要在其中使用引用,但是我不确定这两种选择中的哪种更好(性能更高,但也可能会有一些副作用) ?):

public class CoffeeMachine {

    static int water = 400;
    static int milk = 540;
    static int beans = 120;
    static int cups = 9;
    static int money = 550;
    static boolean exit = false;

    public static void main(String[] args) {
        do {
            printMenu(water,milk,beans,cups,money);
        } while (!exit);
    }

    private static void printMenu(int water,int milk,int beans,int cups,int money) {
        Scanner scanner = new Scanner(system.in);

        System.out.println("Write action (buy,fill,take,remaining,exit): ");
        String input = scanner.nextLine();

        switch (input) {
            case "buy":
                buyOption(water,money);
                break;

            case "fill":
                fillOption(water,money);
                break;

            case "take":
                takeOption(water,money);
                break;

            case "remaining":
                contentOption(water,money);
                break;

            case "exit":
                exit = true;
                System.exit(0);
                break;

            default:
                System.out.println("Wrong option!");
                break;
        }
    }

    private static void contentOption(int water,int money) {
        System.out.println("The coffee machine has: ");
        System.out.println(water + " of water");
        System.out.println(milk + " of milk");
        System.out.println(beans + " of coffee beans");
        System.out.println(cups + " of disposable cups");
        System.out.println(money + " of money");
    }

    private static void buyOption(int water,int money) {
        Scanner scanner = new Scanner(system.in);

        String temp = null;

        System.out.println("What do you want to buy? 1 - espresso,2 - latte,3 - cappuccino: ");

        String input = scanner.nextLine();

        switch (input) {
            case "1":
                if (water >= 250 && beans >= 16 && cups >= 1) {
                    water -= 250;
                    beans -= 16;
                    cups -= 1;
                    money += 4;
                    System.out.println("I have enough resources,making you a coffee!");
                } else {
                    if (water < 250) {
                        temp = "water";
                    } else if (beans < 16) {
                        temp = "beans";
                    } else if (cups < 1) {
                        temp = "cups";
                    }
                    System.out.println("Sorry,not enough " + temp + "!");
                }
                break;

            case "2":
                if (water >= 350 && milk >= 75 && beans >= 20 && cups >= 1) {
                    water -= 350;
                    milk -= 75;
                    beans -= 20;
                    cups -= 1;
                    money += 7;
                    System.out.println("I have enough resources,making you a coffee!");
                } else {
                    if (water < 350) {
                        temp = "water";
                    } else if (milk < 75) {
                        temp = "milk";
                    } else if (beans < 20) {
                        temp = "beans";
                    } else if (cups < 1) {
                        temp = "cups";
                    }
                    System.out.println("Sorry,not enough " + temp + "!");
                }
                break;

            case "3":
                if (water >= 200 && milk >= 100 && beans >= 12 && cups >= 1) {
                    water -= 200;
                    milk -= 100;
                    beans -= 12;
                    cups -= 1;
                    money += 6;
                    System.out.println("I have enough resources,making you a coffee!");
                } else {
                    if (water < 200) {
                        temp = "water";
                    } else if (milk < 100) {
                        temp = "milk";
                    } else if (beans < 12) {
                        temp = "beans";
                    } else if (cups < 1) {
                        temp = "cups";
                    }
                    System.out.println("Sorry,not enough " + temp + "!");
                }
                break;

            case "back":
                break;

            default:
                System.out.println("Wrong option!");
        }
    }

    private static void fillOption(int water,int money) {
        Scanner scanner = new Scanner(system.in);

        System.out.println("Write how many ml of water do you want to add: ");
        water = water + scanner.nextInt();
        System.out.println("Write how many ml of milk do you want to add: ");
        milk = milk + scanner.nextInt();
        System.out.println("Write how many grams of coffee beans do you want to add: ");
        beans = beans + scanner.nextInt();
        System.out.println("Write how many disposable cups of coffee do you want to add: ");
        cups = cups + scanner.nextInt();
    }

    private static void takeOption(int water,int money) {
        System.out.println("I gave you " + money);
        money = 0;
    }
}

选项2:

$array1 = getSomeBigArray();
$array2 = getAnotherBigArray();
$results[] = combineArrays($array1,$array2);

function combineArrays(&$array1,$array2){
   // this is not important,just example of modification
   foreach($array2 as $value){
      if($value > 0){
         $array1[] = $value;
      }
   }
   return $array1;    // will returning $array1 make a copy?
}

编辑: 我已经进行了一些测试,但现在更加困惑了。
这是测试:
https://ideone.com/v7sepC
从这些结果看来,根本不使用引用会更快!并且如果使用的话则是更快的option1(带有返回)。
但是在我的本地环境中,使用引用似乎更快(不是很多)。

编辑2:
ideone.com也许有问题?因为在这里运行相同:
https://3v4l.org/LaffP
结果是: Opcion1和Option2(引用)几乎相等,并且比按值传递更快

解决方法

当您执行return $array1;(在第一个选项中)时,它复制数组,仅增加引用计数器并将引用返回到同一数组。

即函数和$array1的返回值将指向内存中的同一数组。除非您对它们进行任何修改,否则:此时将实际复制数据。

当您为$results[] = $array1;分配值时,实际上不会复制任何数据,只有将引用放入$results的新元素中,这种情况也会发生。

最后,两个选项都具有相同的结果:您将在变量$array1$results的最后一项中引用相同的数据。因此,这两个选项没有明显的性能差异。

此外,请考虑使用本机函数来执行典型操作。例如。 array_merge()

,

代码1:1000000个值,资源:32

代码1:10000000个值,资源:67

代码2:1000000个值,资源:27

代码2:2000000个值,资源:49

我通过调用来计算系统的资源使用量

getrusage

代码2似乎更有效。您可以使用以下代码自己进行一些测试:

<?php 

function getSomeBigArray() {
    $arr = [];
    for ($i=0;$i<2000000;$i++) {
        $arr[] = $i;
    }   
    return $arr;
}

function rutime($ru,$rus,$index) {
    return ($ru["ru_$index.tv_sec"]*1000 + intval($ru["ru_$index.tv_usec"]/1000))
 -  ($rus["ru_$index.tv_sec"]*1000 + intval($rus["ru_$index.tv_usec"]/1000));
}

$array1 = getSomeBigArray();
$array2 = getSomeBigArray();

$rustart = getrusage();
$results[] = combineArrays($array1,$array2);
$ru = getrusage();

echo rutime($ru,$rustart,"utime");

function combineArrays(&$array1,$array2){
    // The array combining method.
}

注意:使用的 rutime方法是通过以下stackoverflow帖子的正确答案复制的:Tracking the script execution time in PHP

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。